JorelAli / CommandAPI

A Bukkit/Spigot API for the command UI introduced in Minecraft 1.13
https://commandapi.jorel.dev
MIT License
504 stars 60 forks source link

worldArgument not updating when new world loaded #531

Closed Aaur1s closed 2 months ago

Aaur1s commented 3 months ago

CommandAPI version

9.3.0

Minecraft version

1.20.4

Are you shading the CommandAPI?

No

What I did

I wrote simple plugin that have 1 command, here's code snippet of command:

object CommandManager {
    private val mainCommand = CommandTree("is").apply {
        literalArgument("test") {
            playerExecutor { player, commandArguments ->
                val world = WorldManager.generateWorld("xdd${Random().nextInt()}") // Invoking WorldCreator#createWorld
                requireNotNull(world)
                world.getBlockAt(world.spawnLocation) // to load it
            }
        }

        literalArgument("tp") {
            worldArgument("world") {
                playerExecutor { player, args ->
                    player.teleport((args["world"] as World).spawnLocation)
                }
            }
        }

        literalArgument("worlds") {
            playerExecutor  { player, args ->
                player.sendMessage(Bukkit.getWorlds().joinToString { it.name })
            }
        }
    }

    fun register() = mainCommand.register() // called in onLoad

    fun unregister() = CommandAPI.unregister(mainCommand.name) // called in onDisable
}

What actually happened

Before is.test invoke:

After is.test invoke:

After player reconnection is.tp suggestions work as expected

What should have happened

After invoking is.test, is.tp worldArgument suggestions should display new worlds

Server logs and CommandAPI config

Aaur1s commented 2 months ago

bump i guess? This thing is still annoying and exists

DerEchtePilz commented 2 months ago

@Aaur1s This might not be exactly what you want to hear but I think this might be working as intended. My suspicion is that when you create the world with your command, only the server knows about that world. This is based on you saying that it works as you want when you reconnect.

I want you to run a small test for me so I can confirm this: Please do everything from your issue description again, but this time instead of relying on suggestions from your /is tp command, please check the world suggestions from /execute in <dimension>. If the behaviour turns out to be same as with your command, there is nothing we can do and this can be labelled as working as intended. However, if the suggestions for the execute in <dimension> command work as you expect your suggestions to work, I guess we can look into this.

DerEchtePilz commented 2 months ago

Okay, I just tested this myself and I can confirm that my suspicion is correct. I registered your commands, and first checked the suggestions for /execute in <dimension>. As expected only the three regular worlds show up.

Secondly, I executed your /is test command and checked if the world was created successfully by executing /is worlds. Again, as expected the newly created world showed up alongside the regular worlds.

Lastly, I checked the suggestions for /execute in <dimension> and as suspected only the three regular worlds show up. Upon reconnecting the world suggestions for /execute in <dimension> also included the new world created by /is test.

So, to summarize: This issue is caused by the world existing for the server but not for the client. If you want to fix this, I believe there definitely is a packet you could utilize to update the worlds for the client.

willkroboth commented 2 months ago

I tested this using Multiverse and a similar thing happened. On Spigot and Paper, after running /mvcreate or /mvremove to create or remove a world, the suggestions for /execute in <dimension> did not update until I rejoined the server. You could probably create an issue with Spigot saying something like WorldCreator#create does not update player suggestions until rejoining.

It may be possible to resend whatever packet the player got when they rejoin to update the argument, but that would probably be hard without NMS. It is possible that someone has already seen this issue before, so there could already be a Spigot API method for updating the client's view of the worlds.

Aaur1s commented 2 months ago

This issue is caused by the world existing for the server but not for the client. If you want to fix this, I believe there definitely is a packet you could utilize to update the worlds for the client.

That's sad, I'll look into patching the core then, ty!

JorelAli commented 2 months ago

In some further discussion on Discord, we believe the Login (play) clientbound packet contains the number of dimensions and the dimensions names present on a server. This information is only sent to a client at login time.

I believe the best situation here would be to override the list of suggestions for the WorldArgument with the list of namespaced dimension names. If acquiring such a list of names proves to be a difficult task, it is probably something the CommandAPI could implement. This solution should probably be added to the CommandAPI's documentation as well.

Aaur1s commented 2 months ago

Wait, I just realized, why worldArgument can't get worlds from Bukkit#getWorlds() ? I don't know how it works, so just making assumptions