Sponge: Offering spectator mode to a player does not work correctly

Created on 17 May 2017  路  13Comments  路  Source: SpongePowered/Sponge

player.offer(Keys.GAME_MODE, GameModes.SPECTATOR);
will result in a somewhat "incomplete" spectator state:

  • Player is entirely invisible rather than a transparent head box being shown
  • Player does _not_ have no-clipping ability

Setting the gamemode manually via /gamemode 3 works normally even if the player is in this pseudo-spectator state.

pr pending data event bug 1.11 (u) 1.12

Most helpful comment

This seems to do the trick to replicate it (tested with SpongeVanilla 1.11.2 (API 6.1.0) BETA-3):

@Listener
public void onSpawn(RespawnPlayerEvent event) {
    if (event.isDeath()) {
        event.getTargetEntity().offer(Keys.GAME_MODE, GameModes.SPECTATOR);
    }
}

Offering it works fine everywhere else - the tab list seems to not update correctly upon respawning if the gamemode is set at this point.

All 13 comments

This is caused by the fact that the gamemode of a player can also be set in the tab list, and if the two gamemodes don't match, behavior like this may occur.

Need some version information on which this is occurring.

This is caused by the fact that the gamemode of a player can also be set in the tab list, and if the two gamemodes don't match, behavior like this may occur.

What do you mean "this"? The data processor that is performing the game mode change is performing the exact same method call as if you were to run the game mode command, there's no tab list modification that needs to take place to make the player a floating head etc.

Happens on SpongeVanilla and SpongeForge - MC 1.11.2 (SpongeAPI 6.1.0).

@gabizou The client player uses 2 different gamemodes, the one set through http://wiki.vg/Protocol#Change_Game_State and one set through http://wiki.vg/Protocol#Player_List_Item, if they don't match on the client, the behavior that @widd specified can occur. I figured this out a while back when I was playing around with those packets.

Cannot reproduce. SpongeForge build 2343 (latest stable 1.11.2) in a development workspace.

Test plugin:

package jbyoshi.sponge.test;

import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandResult;
import org.spongepowered.api.command.args.GenericArguments;
import org.spongepowered.api.command.spec.CommandSpec;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.living.player.gamemode.GameModes;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameInitializationEvent;
import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.text.Text;

@Plugin(id = "testspongecommon1356")
public class TestSpongeCommon1356 {
    @Listener
    public void onInitialization(GameInitializationEvent e) {
        Sponge.getCommandManager().register(this, CommandSpec.builder()
                .arguments(GenericArguments.playerOrSource(Text.of("player")))
                .executor((src, args) -> {
                    ((Player) args.getOne("player").get()).offer(Keys.GAME_MODE, GameModes.SPECTATOR);
                    src.sendMessage(Text.of("You are now spectating"));
                    return CommandResult.success();
                }).build(), "test-c1356");
    }
}

@Cybermaxke The method used internally sends both packets.

@widd Are you also interacting with the TabList api?

@Cybermaxke Not at all. The code I posted is the only thing I'm doing as of right now.

However it occurs upon respawn (dying puts the player in spectator mode once they respawn) - could that be related?

When a Player dies, the player will be regenerated both on the server and client side, this will reset almost everything.
I think I may have an idea why the issue occurs, but I will have to test some things to confirm it.

Ok, I can also not reproduce the issue with the latest bleeding version. The only ways that is issue can occur are:

  • Changing a players tab list entry game mode, to one that doesn't match the players game mode
    -> Can be fixed by setting the proper game mode
  • Removing a player from it's own tab list, and then updating the game mode
    -> Can be fixed by readding the player, and setting the proper game mode

I have no idea why you are having this issue without interacting with the Tab Lists.

Is another mod or plugin interacting with the tablist?

@Cybermaxke As far as I can tell the tab list doesn't update to reflect the gamemode change - I'll see if doing it elsewhere causes the same situation.

@ryantheleach No - this is on a simple test server.

This seems to do the trick to replicate it (tested with SpongeVanilla 1.11.2 (API 6.1.0) BETA-3):

@Listener
public void onSpawn(RespawnPlayerEvent event) {
    if (event.isDeath()) {
        event.getTargetEntity().offer(Keys.GAME_MODE, GameModes.SPECTATOR);
    }
}

Offering it works fine everywhere else - the tab list seems to not update correctly upon respawning if the gamemode is set at this point.

Still happening on 1.12 (bleeding branch).

This is due to the fact that the event is thrown before the player if fully recreated https://github.com/SpongePowered/SpongeCommon/blob/bleeding/src/main/java/org/spongepowered/common/mixin/core/server/MixinPlayerList.java#L551

(As a quick test, moving the event to the end of the method would fix everything, but then you wouldn't be able to change the player location).

I think a good solution would be to throw a RespawnPlayerEvent.Post at the end of the method. (Input wanted)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Xemiru picture Xemiru  路  3Comments

DarkArc picture DarkArc  路  3Comments

randombyte-developer picture randombyte-developer  路  5Comments

XakepSDK picture XakepSDK  路  4Comments

XakepSDK picture XakepSDK  路  5Comments