Giter VIP home page Giter VIP logo

invui's Introduction

Logo

Stars GitHub issues License

InvUI

An Inventory API for Minecraft Spigot servers.
Supports all versions from 1.14.0 to 1.20.6.

Documentation

Features

  • Different types of inventories (Chest, Anvil, Cartography Table, Dropper...)
  • Different GUI types (Normal, Paged, Tab, Scroll)
  • Nested GUIs (For example use a Scroll-GUI as a tab page)
  • Easily customizable (Create your own GUI types and Items)
  • VirtualInventory: Store real items inside GUIs, customize maximum stack size per slot, etc.
  • Easy way to add localization using the ItemProvider system and the built-in ItemBuilder
  • Advanced ItemBuilder (Normal, Potion, Skull, Banner, Firework) with BaseComponent support
  • Support for BaseComponents in inventory titles
  • Uncloseable inventories
  • GUI Animations
  • GUI Builder

Maven

<repository>
    <id>xenondevs</id>
    <url>https://repo.xenondevs.xyz/releases</url>
</repository>
<dependency>
    <groupId>xyz.xenondevs.invui</groupId>
    <artifactId>invui</artifactId>
    <version>VERSION</version>
    <type>pom</type>
</dependency>

Check out the InvUI documentation for more information.

Examples

1 2

invui's People

Contributors

d0gmadev avatar nichtstudiocode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

invui's Issues

this.gui.setContent(); alternative and problem with addItems

image

if(!controlItems.isEmpty()) {
this.gui.setContent(controlItems);
}

public BansGui(LogsManager logsManager) {
    this.logsManager = logsManager;
    this.gui = PagedGui.items()
            .setStructure(
                    "# # # # # # # # #",
                    "# x x x x x x x #",
                    "# x x x x x x x #",
                    "# x x x x x x x #",
                    "# # # < # > # # #"
            ).addIngredient(
                    '#', new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setDisplayName(" "))
            ).addIngredient(
                    '<', new BackItem()
            ).addIngredient(
                    'x', Markers.CONTENT_LIST_SLOT_HORIZONTAL
            ).addIngredient(
                    '>', new ForwardItem()
            ).build();
}

private void prepareGui() {
    for(Logs logs : this.logsManager.getLogs().values()) {



        this.gui.addItems(
            new ControlItem<>() {

                @Override
                public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
                    if(clickType.isLeftClick()) {
                        ChatUtil.sendMessage(player, "&8>> &cPowod: &7" + logs.getReason());
                    }
                }

                @Override
                public ItemProvider getItemProvider(Gui gui) {

                    return new ItemBuilder(logs.getLogsType().getMaterial())
                    .setDisplayName(ChatUtil.fixColor("&f>> &e" + logs.getPunishment() + " &f<<"))
                    .setLegacyLore(
                        ChatUtil.fixColors(
                            Arrays.asList(
                                    "&8>> &7Rodzaj kary: &c" + logs.getLogsType().getName(),
                                    "&8>> &7Administrator: &c" + logs.getPunisher(),
                                    "&8>> &7Powod: &c" + logs.getReason(),
                                    "&8>> &7Czas rozpoczecia: &c" + TimeUtil.getDateFromLong(logs.getTimeStarted().toEpochMilli()),
                                    "&8>> &7Czas: &c" + (logs.getTime() >= 0
                                            ? "PERMANENTNIE" : (logs.getTime() > System.currentTimeMillis()
                                            ? TimeUtil.secondsToString(logs.getTime() - System.currentTimeMillis()) : "zakonczony")
                            )
                        )
                    ));
                }

            }
        );
        

    }
}

public void openGui(Player player) {
    Window window = Window.single()
            .setTitle(ChatUtil.fixColor("&f>> &4Historia banow &f<<"))
            .setViewer(player)
            .setGui(gui)
            .build();

    this.prepareGui();
    window.open();
}

how can i replace a setItems for no dupling

HeadTexture#of prints a stacktrace

There is one problem that worries me. Although you may say that this is not a problem.

If information about a player whose skin is not on the mojang servers is passed to the HeadTexture#of function, then this function will print an error to the console.

My suggestion is to either make a callback to handle the error, or make a throw function.

If you want I can do PR ;)

PageItem class are broken from 1.13-1.19

Using a PagedGUI with trying the examples of the Forward/Back buttons on the documentation causes the buttons to not switch the pages. The last working version of the Forward/Back items is InvUI version 1.12, not sure if one of the functions changed and the documentation hasn't been updated, or if the check was removed.

Repository URL is incorrect

In order for me to utilize your API. I actually had to go to your repository (which really was not easy to find - I suggest a URL on your readme in Github) to find it. I am impressed with your documentation and I am excited to try your API in the plugin I am currently developing. I used:
https://repo.xenondevs.xyz/#/releases

shadowJar is broken for this library

I can't relocate this library anymore using InvUI version >1.27. =<1.27 works.

I used 17 or 21 JVM, still doesn't work

> Task :shadowJar FAILED
ex
org.gradle.api.GradleException: Could not add file '<hidden>' to ZIP '<hidden>-all.jar'.
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:72)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite.access$401(DefaultCallSiteDecorator.java:156)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite$4.callOriginal(DefaultCallSiteDecorator.java:210)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$1.doIntercept(DefaultCallSiteDecorator.java:69)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite.callConstructor(DefaultCallSiteDecorator.java:207)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:286)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction$StreamAction.visitFile(ShadowCopyAction.groovy:243)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:48)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:189)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:57)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction$BaseStreamAction.processFile(ShadowCopyAction.groovy:181)
	at org.gradle.api.internal.file.copy.NormalizingCopyActionDecorator.lambda$execute$0(NormalizingCopyActionDecorator.java:72)
	at org.gradle.api.internal.file.copy.DuplicateHandlingCopyActionDecorator.lambda$execute$0(DuplicateHandlingCopyActionDecorator.java:71)
	at org.gradle.api.internal.file.copy.CopyFileVisitorImpl.processFile(CopyFileVisitorImpl.java:68)
	at org.gradle.api.internal.file.copy.CopyFileVisitorImpl.visitFile(CopyFileVisitorImpl.java:52)
	at org.gradle.api.internal.file.collections.PathVisitor.visitFile(PathVisitor.java:88)
	at org.gradle.api.internal.file.collections.PathVisitor.visitFile(PathVisitor.java:38)
	at java.base/java.nio.file.Files.walkFileTree(Files.java:2786)
	at org.gradle.api.internal.file.collections.DefaultDirectoryWalker.walkDir(DefaultDirectoryWalker.java:44)
	at org.gradle.api.internal.file.collections.DirectoryFileTree.walkDir(DirectoryFileTree.java:147)
	at org.gradle.api.internal.file.collections.DirectoryFileTree.visitFrom(DirectoryFileTree.java:125)
	at org.gradle.api.internal.file.collections.DirectoryFileTree.visit(DirectoryFileTree.java:111)
	at org.gradle.api.internal.file.collections.FileTreeAdapter.visit(FileTreeAdapter.java:110)
	at org.gradle.api.internal.file.CompositeFileTree.visit(CompositeFileTree.java:108)
	at org.gradle.api.internal.file.copy.CopySpecActionImpl.execute(CopySpecActionImpl.java:43)
	at org.gradle.api.internal.file.copy.CopySpecActionImpl.execute(CopySpecActionImpl.java:25)
	at org.gradle.api.internal.file.copy.DefaultCopySpec$DefaultCopySpecResolver.walk(DefaultCopySpec.java:851)
	at org.gradle.api.internal.file.copy.DefaultCopySpec$DefaultCopySpecResolver.walk(DefaultCopySpec.java:853)
	at org.gradle.api.internal.file.copy.DefaultCopySpec.walk(DefaultCopySpec.java:570)
	at org.gradle.api.internal.file.copy.CopySpecBackedCopyActionProcessingStream.process(CopySpecBackedCopyActionProcessingStream.java:42)
	at org.gradle.api.internal.file.copy.DuplicateHandlingCopyActionDecorator.lambda$execute$1(DuplicateHandlingCopyActionDecorator.java:51)
	at org.gradle.api.internal.file.copy.NormalizingCopyActionDecorator.lambda$execute$1(NormalizingCopyActionDecorator.java:64)
	at org.gradle.api.internal.file.copy.CopyActionProcessingStream$process.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction$2.execute(ShadowCopyAction.groovy:108)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction$2$execute.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite.access$101(DefaultCallSiteDecorator.java:156)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite$1.callOriginal(DefaultCallSiteDecorator.java:170)
	at org.gradle.internal.classpath.Instrumented$ProcessGroovyMethodsExecuteInterceptor.doIntercept(Instrumented.java:715)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite.call(DefaultCallSiteDecorator.java:167)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction.withResource(ShadowCopyAction.groovy:150)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
	at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:149)
	at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:100)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:55)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:217)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:240)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction.execute(ShadowCopyAction.groovy:105)
	at org.gradle.api.internal.file.copy.NormalizingCopyActionDecorator.execute(NormalizingCopyActionDecorator.java:63)
	at org.gradle.api.internal.file.copy.DuplicateHandlingCopyActionDecorator.execute(DuplicateHandlingCopyActionDecorator.java:51)
	at org.gradle.api.internal.file.copy.CopyActionExecuter.execute(CopyActionExecuter.java:48)
	at org.gradle.api.tasks.AbstractCopyTask.copy(AbstractCopyTask.java:153)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.copy(ShadowJar.java:161)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:125)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
	at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:244)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
	at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:229)
	at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:212)
	at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:195)
	at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:162)
	at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:105)
	at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:44)
	at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:59)
	at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:56)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:56)
	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:44)
	at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:41)
	at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:74)
	at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
	at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:50)
	at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:28)
	at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:67)
	at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:37)
	at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:61)
	at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:26)
	at org.gradle.internal.execution.steps.CaptureOutputsAfterExecutionStep.execute(CaptureOutputsAfterExecutionStep.java:67)
	at org.gradle.internal.execution.steps.CaptureOutputsAfterExecutionStep.execute(CaptureOutputsAfterExecutionStep.java:45)
	at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:40)
	at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:29)
	at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:189)
	at org.gradle.internal.execution.steps.BuildCacheStep.executeAndStoreInCache(BuildCacheStep.java:145)
	at org.gradle.internal.execution.steps.BuildCacheStep.lambda$executeWithCache$4(BuildCacheStep.java:101)
	at java.base/java.util.Optional.orElseGet(Optional.java:364)
	at org.gradle.internal.execution.steps.BuildCacheStep.lambda$executeWithCache$5(BuildCacheStep.java:101)
	at org.gradle.internal.Try$Success.map(Try.java:164)
	at org.gradle.internal.execution.steps.BuildCacheStep.executeWithCache(BuildCacheStep.java:85)
	at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$0(BuildCacheStep.java:74)
	at org.gradle.internal.Either$Left.fold(Either.java:115)
	at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:62)
	at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:73)
	at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:48)
	at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:46)
	at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:35)
	at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:76)
	at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:54)
	at java.base/java.util.Optional.orElseGet(Optional.java:364)
	at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:54)
	at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:36)
	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37)
	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27)
	at org.gradle.internal.execution.steps.ResolveIncrementalCachingStateStep.executeDelegate(ResolveIncrementalCachingStateStep.java:49)
	at org.gradle.internal.execution.steps.ResolveIncrementalCachingStateStep.executeDelegate(ResolveIncrementalCachingStateStep.java:27)
	at org.gradle.internal.execution.steps.AbstractResolveCachingStateStep.execute(AbstractResolveCachingStateStep.java:71)
	at org.gradle.internal.execution.steps.AbstractResolveCachingStateStep.execute(AbstractResolveCachingStateStep.java:39)
	at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:65)
	at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:36)
	at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:106)
	at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:55)
	at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:64)
	at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:43)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.executeWithNonEmptySources(AbstractSkipEmptyWorkStep.java:125)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:61)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:36)
	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
	at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36)
	at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23)
	at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:75)
	at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:41)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.lambda$execute$0(AssignMutableWorkspaceStep.java:35)
	at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:289)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:31)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:22)
	at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:40)
	at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:23)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:67)
	at java.base/java.util.Optional.orElseGet(Optional.java:364)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:67)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:39)
	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:46)
	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:34)
	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:48)
	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:35)
	at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:61)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:127)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:116)
	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
	at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 65
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:199)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:180)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:166)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:287)
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 65

	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:72)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite.access$401(DefaultCallSiteDecorator.java:156)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite$4.callOriginal(DefaultCallSiteDecorator.java:210)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$1.doIntercept(DefaultCallSiteDecorator.java:69)
	at org.gradle.internal.classpath.intercept.DefaultCallSiteDecorator$DecoratingCallSite.callConstructor(DefaultCallSiteDecorator.java:207)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:277)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction$StreamAction.remapClass(ShadowCopyAction.groovy:339)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:48)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:189)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:57)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:203)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction$StreamAction.remapClass(ShadowCopyAction.groovy:325)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:48)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:189)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:57)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
	at com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction$StreamAction.visitFile(ShadowCopyAction.groovy:239)
	... 189 more

Execution failed for task ':shadowJar'.

Question: Do you have more examples for me?

Hey, great resource!

I was wondering if you had more example GUIs for me to look at. For example, I was wondering how you implement your Animation interface, and/or other GUIs than SimpleGUI

Support for platforms other than Bukkit

I think InvUI is the best library for creating a serverside gui in minecraft, I would really like to use it for example in Minestom.

If you plan to somehow radically change the library, I would very much like the platform code to be separated from the api code

java.lang.IndexOutOfBoundsException on TabGuiImpl#isTabAvailable

This method should check is it the tab exist, but it will throw IndexOutOfBoundsException instead of NULL (for return FALSE)

java.lang.IndexOutOfBoundsException: Index: 2 Size: 2
	at java.util.ImmutableCollections$AbstractImmutableList.outOfBounds(ImmutableCollections.java:333) ~[?:?]
	at java.util.ImmutableCollections$List12.get(ImmutableCollections.java:585) ~[?:?]
	at xyz.xenondevs.invui.gui.TabGuiImpl.isTabAvailable(TabGuiImpl.java:68) ~[?:?]

How to combine PagedGui with VirtualInventory

It seems that adding VirtualInventory as an Ingredient doesn't work, and the only method available for PagedGui is setContent.

I'm really eager to figure out how to combine PagedGui and VirtualInventory effectively to enable page-by-page browsing of VirtualInventory. Any assistance or guidance would be greatly appreciated!

Duplicate - META-INF/MANIFEST.MF inside InvUI Jars.

I tried to get help from InvUI developers in Discord but nobody responded so I went to JetBrains for help. In order to remove the following warnings when running your API I had to include this filter:

[WARNING]   - META-INF/MANIFEST.MF
[WARNING] maven-shade-plugin has detected that some class files are   
[WARNING] present in two or more JARs. When this happens, only one   
[WARNING] single version of the class is copied to the uber jar.   
[WARNING] Usually this is not harmful and you can skip these warnings,   
[WARNING] otherwise try to manually exclude artifacts based on   
[WARNING] mvn dependency:tree -Ddetail=true and the above output.

Filter:

<filters>
  <filter>
      <artifact>de.studiocode.invui:*</artifact>
      <excludes>
          <exclude>META-INF/*.MF</exclude>
      </excludes>
  </filter>
  <filter>
      <artifact>org.jetbrains:annotations:*</artifact>
      <excludes>
          <exclude>META-INF/*.MF</exclude>
      </excludes>
  </filter>
</filters>

Paged Tabs GUI support

In some cases you want to create a gui where you want to have tabs paged. So what I mean is, you have the control items from the tab ui and you can navigate across multiple pages.

ClassNotFoundException in PaperMC 1.19.4

I encountered the following errors.

[09:35:15 WARN]: java.lang.ClassNotFoundException: xyz.xenondevs.inventoryaccess.r13.InventoryUtilsImpl
[09:35:15 WARN]: 	at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:183)
[09:35:15 WARN]: 	at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:150)
[09:35:15 WARN]: 	at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
[09:35:15 WARN]: 	at java.base/java.lang.Class.forName0(Native Method)
[09:35:15 WARN]: 	at java.base/java.lang.Class.forName(Unknown Source)
[09:35:15 WARN]: 	at DepositVault.jar//xyz.xenondevs.inventoryaccess.util.ReflectionUtils.getImplClass(ReflectionUtils.java:28)
[09:35:15 WARN]: 	at DepositVault.jar//xyz.xenondevs.inventoryaccess.InventoryAccess.<clinit>(InventoryAccess.java:20)
[09:35:15 WARN]: 	at DepositVault.jar//xyz.xenondevs.invui.window.AbstractWindow.openInventory(AbstractWindow.java:306)
[09:35:15 WARN]: 	at DepositVault.jar//xyz.xenondevs.invui.window.AbstractWindow.open(AbstractWindow.java:302)
[09:35:15 WARN]: 	at DepositVault.jar//com.skuralll.depositvault.ui.GUI.open(GUI.java:31)
[09:35:15 WARN]: 	at DepositVault.jar//com.skuralll.depositvault.listener.PlayerEventListener.onPlayerInteract(PlayerEventListener.java:113)
[09:35:15 WARN]: 	at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor29.execute(Unknown Source)
[09:35:15 WARN]: 	at org.bukkit.plugin.EventExecutor$2.execute(EventExecutor.java:77)
[09:35:15 WARN]: 	at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:81)
[09:35:15 WARN]: 	at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70)
[09:35:15 WARN]: 	at io.papermc.paper.plugin.manager.PaperEventManager.callEvent(PaperEventManager.java:54)
[09:35:15 WARN]: 	at io.papermc.paper.plugin.manager.PaperPluginManagerImpl.callEvent(PaperPluginManagerImpl.java:126)
[09:35:15 WARN]: 	at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:615)
[09:35:15 WARN]: 	at org.bukkit.craftbukkit.v1_19_R3.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:562)
[09:35:15 WARN]: 	at net.minecraft.server.level.PlayerInteractManager.a(PlayerInteractManager.java:536)
[09:35:15 WARN]: 	at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1958)
[09:35:15 WARN]: 	at net.minecraft.network.protocol.game.PacketPlayInUseItem.a(PacketPlayInUseItem.java:37)
[09:35:15 WARN]: 	at net.minecraft.network.protocol.game.PacketPlayInUseItem.a(PacketPlayInUseItem.java:9)
[09:35:15 WARN]: 	at net.minecraft.network.protocol.PlayerConnectionUtils.lambda$ensureRunningOnSameThread$0(PlayerConnectionUtils.java:51)
[09:35:15 WARN]: 	at net.minecraft.server.TickTask.run(TickTask.java:18)
[09:35:15 WARN]: 	at net.minecraft.util.thread.IAsyncTaskHandler.d(IAsyncTaskHandler.java:153)
[09:35:15 WARN]: 	at net.minecraft.util.thread.IAsyncTaskHandlerReentrant.d(IAsyncTaskHandlerReentrant.java:24)
[09:35:15 WARN]: 	at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1342)
[09:35:15 WARN]: 	at net.minecraft.server.MinecraftServer.d(MinecraftServer.java:197)
[09:35:15 WARN]: 	at net.minecraft.util.thread.IAsyncTaskHandler.x(IAsyncTaskHandler.java:126)
[09:35:15 WARN]: 	at net.minecraft.server.MinecraftServer.bi(MinecraftServer.java:1319)
[09:35:15 WARN]: 	at net.minecraft.server.MinecraftServer.x(MinecraftServer.java:1312)
[09:35:15 WARN]: 	at net.minecraft.util.thread.IAsyncTaskHandler.c(IAsyncTaskHandler.java:136)
[09:35:15 WARN]: 	at net.minecraft.server.MinecraftServer.i_(MinecraftServer.java:1290)
[09:35:15 WARN]: 	at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1178)
[09:35:15 WARN]: 	at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:320)
[09:35:15 WARN]: 	at java.base/java.lang.Thread.run(Unknown Source)

I use Java to create my plugins and have written gradle as per the documentation.
No error is output at compile time, but the above error is output when actually trying to open the UI in the server.

My server's version is Paper version git-Paper-509 (MC: 1.19.4) (Implementing API version 1.19.4-R0.1-SNAPSHOT) (Git: e338793)

Thank you for your help

How to Creating a scalable auto-adjusting size inventory

Hi there,

I am facing an issue related to the Inventory interface in our project. Currently, we have an implementation called VirtualInventory that does not include the width and height properties. However, the VirtualInventory does have a size property.

My goal is to create a custom Inventory implementation that can automatically adjust its size based on the items it contains. I'm seeking guidance on how to achieve this effectively.

Any suggestions or code examples on how to approach this problem would be greatly appreciated. Thank you in advance for your assistance!

AutoUpdateItem starts an infinite BukkitTask

Unlike AutoCycleItem, the task inside an AutoUpdateItem is never stopped, even after the closure of every linked Windows, leading to an inconsistency between the example items, as well as potentially saturating the program with BukkitTasks.

Is it anyway to check a player is opening InvUI's inventory(Gui) ?

Im wonder is it anyway to check a player is opening InvUI's Gui?
Or I just need to loop all Windows and check the viewer

Can you consider to add a custom bukkit inventory holder to the bukkit's inventory?
So we can inventory.getHolder() instanceof XXXXXX to check wheather player is opening the Gui

Different behaviour of shift-click item move to player's inventory

When item taken from InvUI inventory using shift-click, then item placed in different position in player's inventory than position would be if item taken from vanilla inventory.

Setup of inventories:
Vanilla inventory
Vanilla inventory
InvUI inventory
InvUI inventory

Positions after shift-click on item:
Vanilla behaviour:
Hotbar is clear
Hotbar is clear
Hotbar is filled
Hotbar is filled

InvUI behaviour:
Hotbar is clear
Hotbar is clear
Hotbar is filled
Hotbar is filled

Adding items using addItems method on SimpleGUI does not seem to work when creating a Tab GUI

Version 0.10

I was creating a tab GUI and the example worked great, I then tried just adding specific items using the addItems method instead of using the fill method and it would not add any items.

I stepped into the method below and the emptyIndex was constantly coming back as -1, why it was doing that I am not sure, since the GUI had not had any items added to it yet.

    @Override
    public void addItems(@NotNull Item... items) {
        for (Item item : items) {
            int emptyIndex = ArrayUtils.findFirstEmptyIndex(items);
            if (emptyIndex == -1) break;
            setItem(emptyIndex, item);
        }
    }

This is the code to reproduce the GUI that isnt working, this exact code works perfectly fine with using fill or setItem

  GUI pickaxeTab = new SimpleGUI(9, 3);
  GUI axeTab = new SimpleGUI(9, 3);
  for (int i =0; i < 9; i++){
      pickaxeTab.addItems(new SimpleItem(new ItemBuilder(Material.IRON_PICKAXE)));
      axeTab.addItems(new SimpleItem(new ItemBuilder(Material.IRON_AXE)));
  }
  menu = new GUIBuilder<>(GUIType.TAB)
          .setStructure(
                  "# # # 0 # 1 # # #",
                  "x x x x x x x x x",
                  "x x x x x x x x x",
                  "x x x x x x x x x")
          .addIngredient('x', Markers.ITEM_LIST_SLOT_HORIZONTAL)
          .addIngredient('#', Border::new)
          .addIngredient('0', new PickTab(0))
          .addIngredient('1', new AxeTab(1))
          .setGUIs(Arrays.asList(pickaxeTab, axeTab))
          .build();
}

Impossible change title on 1.19.4

I get this error when trying update inventory title.

[DefaultDispatcher-worker-21/WARN]: java.lang.UnsupportedOperationException: Unable to construct this menu by type
[DefaultDispatcher-worker-21/WARN]: 	at net.minecraft.world.inventory.Container.a(Container.java:126)
[DefaultDispatcher-worker-21/WARN]: 	at MtDialog-1.0.0.jar//ru.minetopia.mtdialog.shadow.invui.inventoryaccess.r13.InventoryUtilsImpl.updateOpenInventoryTitle(InventoryUtilsImpl.java:69)
[DefaultDispatcher-worker-21/WARN]: 	at MtDialog-1.0.0.jar//ru.minetopia.mtdialog.shadow.invui.invui.window.AbstractWindow.changeTitle(AbstractWindow.java:306)

GUI Init code

val gui = Gui.normal()
    .setStructure(
        ". . . . . . . . .",
        ". . . . . . . . .",
        ". . . . . . . . .",

        ". . . . . . . . .",
        "0 0 0 0 . 1 1 1 1",
        ". . . . . . . . .",
        "2 2 2 2 . 3 3 3 3",
    )
    .apply {
        repeat(4) { i ->
            addIngredient(i.digitToChar(), SimpleItem(item(i)) { click(i) })
        }
    }
    .build()

window = Window
    .merged()
    .setGui(gui)
    .setTitle(AdventureComponentWrapper(createBuilder().build()))
    .build(player)

Title change code

window.changeTitle(AdventureComponentWrapper(builder.build()))

Server: Pufferfish 1.19.4
InvUI: xyz.xenondevs.invui:invui:1.0-SNAPSHOT

Can't use the dependency in maven for some reason

When I use the maven details you gave me I get an error that the dependency was not found in the spigot(?) repository, despite me adding your repository. Is this a common issue? Despite the error I can use your libraries and it works but I can't build.

Inventories PagedGui pagination behavior is abnormal

The pagination of Inventories PagedGui is not functioning correctly. The result of "${gui.currentPage} / ${gui.pageAmount}" is always 0 / 1.

Below is a code snippet that reliably reproduces the issue:

import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import xyz.xenondevs.invui.gui.PagedGui
import xyz.xenondevs.invui.gui.structure.Markers
import xyz.xenondevs.invui.inventory.VirtualInventory
import xyz.xenondevs.invui.inventory.event.UpdateReason
import xyz.xenondevs.invui.item.ItemProvider
import xyz.xenondevs.invui.item.builder.ItemBuilder
import xyz.xenondevs.invui.item.impl.SimpleItem
import xyz.xenondevs.invui.item.impl.controlitem.PageItem
import xyz.xenondevs.invui.window.Window

private fun openTestGui(player: Player) {
    val inv = VirtualInventory(999)
    repeat(999) {
        inv.addItem(UpdateReason.SUPPRESSED, ItemStack(Material.STONE, 64))
    }

    val gui = PagedGui.inventories().apply {
        setStructure(
            "xxxxxxxxx",
            "xxxxxxxxx",
            "xxxxxxxxx",
            "xxxxxxxxx",
            "xxxxxxxxx",
            "###<#>###"
        )
        addIngredient('x', Markers.CONTENT_LIST_SLOT_VERTICAL)
        addIngredient('#', SimpleItem(ItemStack(Material.GRAY_STAINED_GLASS_PANE)))
        addIngredient('<', object : PageItem(false) {
            override fun getItemProvider(gui: PagedGui<*>): ItemProvider =
                ItemBuilder(Material.RED_STAINED_GLASS_PANE).apply {
                    setDisplayName("Back")
                        .addLoreLines(
                            "Back ${gui.currentPage} / ${gui.pageAmount}"
                        )
                }
        })
        addIngredient('>', object : PageItem(true) {
            override fun getItemProvider(gui: PagedGui<*>): ItemProvider =
                ItemBuilder(Material.GREEN_STAINED_GLASS_PANE).apply {
                    setDisplayName("Forward")
                        .addLoreLines(
                            "Forward ${gui.currentPage} / ${gui.pageAmount}"
                        )
                }
        })
        setContent(listOf(inv))
    }.build()

    val window = Window.single().apply {
        setViewer(player)
        setTitle("InvUI Test")
        setGui(gui)
    }.build()

    window.open()
}

Image

InvUI pom.xml Invalid

I'm getting this error when building my plugin:

Invalid POM for , transitive dependencies (if any) will not be available, enable debug logging for more details

In my case, my machine builds the plugin just fine due to transitive dependencies being stored in a cache.

However, on any other machine, this becomes a problem as there is no current cache for transitive dependencies such as de.studiocode.inventoryaccess.

If you could help me with this in any way that would be of great help.

Is there support for 1.19.4

It says 1.19 support but I loaded into my 1.19.4 server and this happens. Any ideas what might cause this or is the package just not updated for 1.19.4?

org.bukkit.command.CommandException: Unhandled exception executing command 'ml' in plugin MLcore v1.0-SNAPSHOT
	at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[paper-api-1.19.4-R0.1-SNAPSHOT.jar:?]
	at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:155) ~[paper-api-1.19.4-R0.1-SNAPSHOT.jar:?]
	at org.bukkit.craftbukkit.v1_19_R3.CraftServer.dispatchCommand(CraftServer.java:906) ~[paper-1.19.4.jar:git-Paper-499]
	at org.bukkit.craftbukkit.v1_19_R3.command.BukkitCommandWrapper.run(BukkitCommandWrapper.java:64) ~[paper-1.19.4.jar:git-Paper-499]
	at com.mojang.brigadier.CommandDispatcher.execute(CommandDispatcher.java:264) ~[paper-1.19.4.jar:?]
	at net.minecraft.commands.Commands.performCommand(Commands.java:322) ~[?:?]
	at net.minecraft.commands.Commands.performCommand(Commands.java:306) ~[?:?]
	at net.minecraft.server.network.ServerGamePacketListenerImpl.performChatCommand(ServerGamePacketListenerImpl.java:2289) ~[?:?]
	at net.minecraft.server.network.ServerGamePacketListenerImpl.lambda$handleChatCommand$20(ServerGamePacketListenerImpl.java:2249) ~[?:?]
	at net.minecraft.util.thread.BlockableEventLoop.lambda$submitAsync$0(BlockableEventLoop.java:59) ~[?:?]
	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ~[?:?]
	at net.minecraft.server.TickTask.run(TickTask.java:18) ~[paper-1.19.4.jar:git-Paper-499]
	at net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:153) ~[?:?]
	at net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:24) ~[?:?]
	at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:1342) ~[paper-1.19.4.jar:git-Paper-499]
	at net.minecraft.server.MinecraftServer.d(MinecraftServer.java:197) ~[paper-1.19.4.jar:git-Paper-499]
	at net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:126) ~[?:?]
	at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:1319) ~[paper-1.19.4.jar:git-Paper-499]
	at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:1312) ~[paper-1.19.4.jar:git-Paper-499]
	at net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:136) ~[?:?]
	at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:1290) ~[paper-1.19.4.jar:git-Paper-499]
	at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1178) ~[paper-1.19.4.jar:git-Paper-499]
	at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:320) ~[paper-1.19.4.jar:git-Paper-499]
	at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: java.lang.NoClassDefFoundError: org/bukkit/craftbukkit/v1_19_R2/inventory/CraftContainer
	at java.lang.Class.forName0(Native Method) ~[?:?]
	at java.lang.Class.forName(Class.java:375) ~[?:?]
	at de.studiocode.inventoryaccess.util.ReflectionUtils.getImplClass(ReflectionUtils.java:31) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.inventoryaccess.version.InventoryAccess.<clinit>(InventoryAccess.java:18) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.item.builder.BaseItemBuilder.get(BaseItemBuilder.java:87) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.item.builder.ItemBuilder.get(ItemBuilder.java:8) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.item.builder.BaseItemBuilder.getFor(BaseItemBuilder.java:142) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.item.builder.ItemBuilder.getFor(ItemBuilder.java:8) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.gui.SlotElement$ItemSlotElement.getItemStack(SlotElement.java:35) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.BaseWindow.redrawItem(BaseWindow.java:69) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.single.SingleWindow.initItems(SingleWindow.java:40) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.single.SingleWindow.<init>(SingleWindow.java:34) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.single.SimpleWindow.<init>(SimpleWindow.java:16) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.single.SimpleWindow.<init>(SimpleWindow.java:33) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.single.SimpleWindow.<init>(SimpleWindow.java:49) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.single.SimpleWindow.<init>(SimpleWindow.java:57) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at de.studiocode.invui.window.impl.single.SimpleWindow.<init>(SimpleWindow.java:61) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at tanko.mlcore.guis.menus.MLMenu.open(MLMenu.java:25) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at tanko.mlcore.commands.ML.mlMain(ML.java:195) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at tanko.mlcore.commands.ML.onCommand(ML.java:51) ~[MLcore-1.0-SNAPSHOT.jar:?]
	at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[paper-api-1.19.4-R0.1-SNAPSHOT.jar:?]
	... 23 more

Bold formatting not resetting in lore

If I set a lore using the setLegacyLore method, some format is messed up.
As an example if I use the following:
&lHello &rWorld

The World word is in bold even if I've used the &r.

NoClassDefFoundError: xyz/xenondevs/invui/item/ItemProvider on Spigot 1.20

I received a ClassNotFoundException in my server console upon loading my plugin. The full console error, my plugin code, and the repositories + dependencies section of my build.gradle have been linked below. Any ideas as to why the plugin is not loading? It loads fine when I comment out the code containing the InvUI API.

Server is Spigot 1.20, and I am using InvUI 1.23

image
image
image

It is possible to take Item from the GUI

Hello. When using shift+click at ScrollGui, it is possible to take item to player inventory.

Paper 1.16.5. Kotlin.

    private fun openFactoryGui(player: Player, factory: PlacedFactory) {
        val productionGui = ScrollGui.items()
            .setStructure(
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x"
            )
            .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL)
            .setContent(factory.config.items.map { ProductionItem(factory, it) })
            .build()

        val inputInventoryGui = Gui.normal()
            .setStructure(
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x"
            )
            .addIngredient('x', factory.inputInventory)
            .build()

        val outputInventory = factory.outputInventory
        outputInventory.setPreUpdateHandler { if (it.isAdd) it.isCancelled = true }

        val outputInventoryGui = Gui.normal()
            .setStructure(
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x"
            )
            .addIngredient('x', factory.outputInventory)
            .build()


        val tabGui = TabGui.normal()
            .setStructure(
                "# # 0 1 # 2 3 # #",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x",
                "x x x x x x x x x"
            )
            .setTabs(listOf(productionGui, inputInventoryGui, outputInventoryGui))
            .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL)
            .addIngredient('0', TabButton(Material.IRON_PICKAXE, Component.text("Производство"), 0))
            .addIngredient('1', TabButton(Material.CHEST, Component.text("Инвентарь станка"), 1))
            .addIngredient('2', TabButton(Material.ENDER_CHEST, Component.text("Готовые вещи"), 2))
            .addIngredient('3', InfoButton(factory))
            .addIngredient('#', ItemBuilder(Material.GRAY_STAINED_GLASS_PANE).setDisplayName(Component.empty()))
            .build()

        server.scheduler.runTask(plugin, Runnable {
            Window.single()
                .setGui(tabGui)
                .setTitle("Станок")
                .build(player)
                .open()
        })
    }

I use tab gui with 3 tabs - ScrollGui and 2 Virtual Inventories (Gui). Player can extract item from the ScrollGui, what is completely unexpected.

Items stay in your inventory after server restart when using multi window

Whenever you use a multi window and the server crashes, the items don't get restored after joining back.

Since the contents are already saved and restored...
note

...would it be possible to serialize and save the player's inventory in a file (maybe datebase even) upon the server close?

private final ItemStack[] playerItems = new ItemStack[36];

This way, whenever a player joins back, it would see if the inventory was restored. If not, deserialize the data and:

private void restorePlayerInventory() {
Inventory inventory = getViewer().getInventory();
for (int i = 0; i < 36; i++) {
inventory.setItem(i, playerItems[i]);
}
}

The GUI doesn't load on 1.19.4

my build.gradle

    dependencies {

    implementation 'org.projectlombok:lombok:1.18.22'
    implementation 'xyz.xenondevs.invui:invui-core:1.8'
    implementation 'xyz.xenondevs.invui:inventory-access-r13:1.8:remapped-mojang'
    compileOnly "org.spigotmc:spigot-api:1.19.4-R0.1-SNAPSHOT"

    implementation "dev.jorel:commandapi-bukkit-shade:9.0.1"

    implementation 'com.github.Exlll.ConfigLib:configlib-yaml:v4.2.0'

    annotationProcessor('org.projectlombok:lombok:1.18.26')

}
shadowJar {
    dependencies {
        include dependency("dev.jorel:commandapi-bukkit-shade:9.0.1")

        include dependency('com.github.stefvanschie.inventoryframework:IF:0.10.9')
        include dependency("com.github.Exlll.ConfigLib:configlib-yaml:v4.2.0")
        include dependency("xyz.xenondevs.invui:invui-core:1.8")
        include dependency("xyz.xenondevs.invui:inventory-access-r13:1.8:remapped-mojang")
    }
    relocate("dev.jorel.commandapi", "dev.unnm3d.lib.commandapi")

    relocate 'de.exlll.configlib', 'dev.unnm3d.lib.configlib'
    relocate 'xyz.xenondevs.invui', 'dev.unnm3d.lib.invui'
    relocate 'xyz.xenondevs.inventoryaccess', 'dev.unnm3d.lib.inventoryaccess'
}

my command with default code

        return new CommandAPICommand("kgui")
                .executesPlayer((player, args) -> {
                    Bukkit.getLogger().info("test");
                    SimpleItem border = new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE));
                    Gui gui = Gui.normal()
                            .setStructure(
                                    "# # # # # # # # #",
                                    "# . . . . . . . #",
                                    "# . . . . . . . #",
                                    "# # # # # # # # #")
                            .addIngredient('#', border)
                            .build();
                    Window window = Window.single()
                            .setViewer(player)
                            .setGui(gui)
                            .setTitle("InvUI")
                            .build();
                    window.open();


                });

console sends "test" but the gui is not displayed to player
i chose this library because i can modify the bottom inventory of the player but it is the only library that doesn't work at all without any error on console

Trivial item duplication exploit in InvUI caused by `BaseWindow#close`

I've made a voting plugin that uses InvUI, but after the GUI is closed users can duplicate items.
I'm able to reproduce this issue on Paper 1.18.2 and 1.19.2 respectively.

Below is a Paper plugin I made for this issue that can reproduce the exploit.

Plugin JAR: itemdup-1.0-all.jar
Plugin source: invui-itemdup-exploit

Reproduction steps:

    1. Download/Build and install the plugin on a Paper 1.18/1.19 server like usual (this plugin uses Paper API)
    1. Log into the server
    1. Observe that the exploit does not work
    1. Type opengui in chat, and wait for the GUI to close after 3 seconds
    1. Observe that the exploit does work.

Additional:

    1. Leave the server
    1. Observe that the exploit no longer works
    1. Follow step 4
    1. Observe that the exploit works again like in step 5

Before a GUI is opened:

before_gui.mp4

As you can see, everything works as usual here. There's no item duplication exploit. Now, let's run /vote which will open a GUI:

After a GUI is opened:

after_gui.mp4

What is happening here?! There's a very bad item duplication exploit that is trivial to abuse. I'm unable to use this plugin on my server at the moment, because of this exploit.

One important note: I'm able to reproduce this issue consistently when shift clicking and dragging as shown in the video above.
The reason why this happens still eludes me. I'm using InvUI version 0.8-SNAPSHOT: de.studiocode.invui:InvUI:0.8-SNAPSHOT.

Actually, while writing the test plugin (the block above was written before), I found out that this issue is caused by window.close.
If you close the UI yourself, the exploit doesn't occur. But only when window.close is called, does it occur.
When you leave, the exploit is gone. You have to open the GUI again, and then the exploit is back.

https://github.com/Sculas/invui-itemdup-exploit/blob/eb4dcd37f013d946ea42d6eb90e9bc87ef589455/src/main/java/xyz/sculas/itemdup/ItemDup.java#L31-L36

Cannot inherit from BaseItemBuilder

Hi @NichtStudioCode ,
I'm trying to make my own ItemBuilder by extending BaseItemBuilder in my project as suggested in the docs, but i can't because the abstract class is package-private : abstract class BaseItemBuilder<T> implements ItemProvider {

the example Builders can't be inherited at all because they're final (which makes sense), except for PotionBuilder (?)

What is the expected behaviour ?
Thanks

Ghost items when hotkey-swapping to off-hand on Spigot

I really love what this framework provides, so i hope youll keep on developing it.

Issue:
Inventory click with offhand causes *possible item duplication, to replicate it:
Create any GUI, for example like one in wiki:

Gui gui = Gui.normal()
        .setStructure(
                "# # # # # # # # #",
                "# . . . . . . . #",
                "# . . . . . . . #",
                "# # # # # # # # #")
        .addIngredient('#', new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE)))
        .build();

Window window = Window.single()
        .setViewer(player)
        .setTitle("InvUI")
        .setGui(gui)
        .build();

window.open();

open it in-game, and then press offhand switch (by default F key) while cursor is on any item.

  • In creative:
    once player closes inventory item in their offhand will be crafted and cause a InventoryCreativeEvent
  • In survival:
    once player closes inventory item in their offhand will stay as a ghost item

Suggested resolution:
In InventoryClickEvent: event.getPlayer().getInventory().setItemInOffHand(event.getPlayer().getInventory().getItemInOffHand());
Im not sure that event.getPlayer().updateInventory() works properly in this case

Issue on opening GUI

[17:46:41 WARN]: [HuskTowns] Task #12368 for HuskTowns v2.5.4-561c472-indev generated an exception
java.lang.ExceptionInInitializerError: null
        at net.william278.husktowns.libraries.invui.window.NormalMergedWindowImpl$BuilderImpl.build(NormalMergedWindowImpl.java:44) ~[HuskTowns-Plugin-2.5.4-561c472-indev.jar:?]
        at net.william278.husktowns.libraries.invui.window.AbstractWindow$AbstractBuilder.open(AbstractWindow.java:570) ~[HuskTowns-Plugin-2.5.4-561c472-indev.jar:?]
        at dev.unnm3d.kalyaclaims.gui.BukkitGUIManager.lambda$openTownGUI$0(BukkitGUIManager.java:153) ~[HuskTowns-Plugin-2.5.4-561c472-indev.jar:?]
        at org.bukkit.craftbukkit.v1_20_R1.scheduler.CraftTask.run(CraftTask.java:101) ~[purpur-1.20.1.jar:git-Purpur-2044]
        at org.bukkit.craftbukkit.v1_20_R1.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:480) ~[purpur-1.20.1.jar:git-Purpur-2044]
        at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1507) ~[purpur-1.20.1.jar:git-Purpur-2044]
        at net.minecraft.server.dedicated.DedicatedServer.tickChildren(DedicatedServer.java:487) ~[purpur-1.20.1.jar:git-Purpur-2044]
        at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1421) ~[purpur-1.20.1.jar:git-Purpur-2044]
        at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1192) ~[purpur-1.20.1.jar:git-Purpur-2044]
        at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:323) ~[purpur-1.20.1.jar:git-Purpur-2044]
        at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Class.isInstance(Object)" because "net.william278.husktowns.libraries.inventoryaccess.util.ReflectionRegistry.PAPER_PLUGIN_CLASS_LOADER_CLASS" is null
        at net.william278.husktowns.libraries.invui.InvUI.tryFindPlugin(InvUI.java:50) ~[HuskTowns-Plugin-2.5.4-561c472-indev.jar:?]
        at net.william278.husktowns.libraries.invui.InvUI.getPlugin(InvUI.java:36) ~[HuskTowns-Plugin-2.5.4-561c472-indev.jar:?]
        at net.william278.husktowns.libraries.invui.window.AbstractWindow.<clinit>(AbstractWindow.java:42) ~[HuskTowns-Plugin-2.5.4-561c472-indev.jar:?]
        ... 11 more

it is shaded
running on Purpur 1.20.1 (might be this)

my gradle

implementation "xyz.xenondevs.invui:invui-core:1.15"
implementation "xyz.xenondevs.invui:inventory-access-r14:1.15"
...
relocate 'xyz.xenondevs', 'net.william278.husktowns.libraries'

Translation color issue

Hi, while changing my String litterals to translated components, I faced this unexpected behaviour regarding the translation of custom colors, as they appear wrongly (InvUI 1.0 & Spigot 1.19)

Here is my test code:

String coloredString1 = net.md_5.bungee.api.ChatColor.DARK_PURPLE + "purple";
String coloredString2 = net.md_5.bungee.api.ChatColor.of("#4e6654") + "colored";
String coloredString3 = "§7gray";

Languages.getInstance().addLanguage("test-lang", Map.of("1", coloredString1, "2", coloredString2, "3", coloredString3));
Languages.getInstance().setLanguageProvider(p -> "test-lang");

player.sendMessage(coloredString1, coloredString2, coloredString3);
player.sendMessage(Languages.getInstance().getFormatString("test-lang", "1"),
   Languages.getInstance().getFormatString("test-lang", "2"),
   Languages.getInstance().getFormatString("test-lang", "3")
);

Item testItem = new SimpleItem(new ItemBuilder(Material.BOOK).addLoreLines(coloredString1, coloredString2, coloredString3));
Item translateItem = new SimpleItem(new ItemBuilder(Material.BOOK).addLoreLines(
   new BaseComponent[]{new TranslatableComponent("1")},
   new BaseComponent[]{new TranslatableComponent("2")},
   new BaseComponent[]{new TranslatableComponent("3")}
));

Gui g = Gui.normal().setStructure("..a...b..").addIngredient('a', testItem).addIngredient('b', translateItem).build();
Window.single().setTitle("TITLE").setGui(g).open(player);

I expected to get two similar items, but this is the result:

2023-04-11_18 51 37
2023-04-11_18 51 38

In this example it appears red, but for other custom colors it might appear white or any other color.
However, the two sendMessage() produce expected results.
Thank you for your help

Strange behaviour when trying to update an item inside Anvil result slot

Hi, I'm having trouble using the AnvilWindow and I don't know why...
In the past versions this system worked well, but now all the anvil GUI just have a really strange behaviour.

I'm trying to make and AnvilGUI that takes an input, but also validates it.
So, when you see the X icon, the player can't confirm, when you see the V icon, the player can confirm and a function will be executed.

In this case, just for testing, it will check if the input is a number and if its != 1.

The code is working, the problem is the anvil GUI itself...

This is the functions to request an input from the user:
https://pastebin.com/mFQshPhq

This is the class AnvilItem used to update the result slot of the anvil:
https://pastebin.com/q9072SZx

This is what happens every time I change the text of the anvil:
https://imgur.com/a/RbXz26d

The player inventory should remain untouched, but this strange bug occurs and I tried everything to fix this, with no success, as the icon should be only in the result slot of the anvil.

And if the player closed the GUI, all the items remains in its inventory...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.