Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SpectateLogin implementation #2552

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

mrchefran
Copy link

Implementation of the idea proposed in #2503

Feature description: puts the player in an invisible armorstand for the time of authorization and fixes the direction of the view. After authorization is completed, the stand disappears

@sgdc3
Copy link
Member

sgdc3 commented Jun 3, 2022

Looks cool! I'll take a look asap, in the meantime @ljacqu @games647 @hex3l what do you think about this concept+implementation?

@sgdc3 sgdc3 requested review from ljacqu, hex3l, sgdc3 and games647 June 4, 2022 00:02
@@ -191,6 +195,15 @@ private void processJoinSync(Player player, boolean isAuthAvailable) {
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
}

if (service.getProperty(RestrictionSettings.SPECTATE_STAND_LOGIN)) {
// The delay is necessary in order to make sure that the player is teleported to spawn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about listening at the player spawn/respawn event?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+ doesn't the armor stand have to be deleted if the player disconnects as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about listening at the player spawn/respawn event?

Looks like this will also require a delay, because at this stage it's impossible to change the player gamemode

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • doesn't the armor stand have to be deleted if the player disconnects as well?

Armorstands are removed if an unauthorized player leaves the server

Copy link
Member

@ljacqu ljacqu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks great and you've found a great way to incorporate the changes into the existing codebase! Some unit tests would be nice :)

import java.util.HashMap;
import java.util.Map;

public class SpectateLoginService {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good name! Allows us to remember that this will set players to SPECTATOR game mode :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a description of the class behavior

}

public boolean hasStand(Player player) {
return armorStands.get(player) != null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be armorStands.containsKey(player)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to it


@Comment("Head Pitch position for 'spectateStandLogin'.")
public static final Property<Double> HEAD_PITCH =
newProperty("settings.restrictions.headPitch", 0.0f);
Copy link
Member

@ljacqu ljacqu Jun 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to put the new properties under a dedicated path? In the sense of settings.restrictions.spectateStandLogin.pitch (or .headPitch). With that naming, settings.restrictions.spectateStandLogin would have to become something like "settings.restrictions.spectateStandLogin.enabled"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it would. It looks much better this way. I put the properties in a separate path

&& event.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE
&& event.getPlayer().getGameMode() == GameMode.SPECTATOR
&& (settings.getProperty(RestrictionSettings.SPECTATE_STAND_LOGIN)
|| spectateLoginService.hasStand(event.getPlayer()))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this checks out since listenerService.shouldCancelEvent(event.getPlayer()) will be false if the player is logged in, right? In other words, even when we enable a feature, players can still teleport to other players in spectate mode once they've logged in

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These checks are designed to prevent unauthorized players from teleporting (using hotbar) while they are in spectator gamemode

Location location = new Location(loc.getWorld(), loc.getX(), loc.getY(), loc.getBlockZ(),
(float) yaw, (float) pitch);

ArmorStand stand = location.getWorld().spawn(location, ArmorStand.class);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this cause issues if two players have the same location?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not affect the position of the stand in any way. The only thing is that players can see the stands of others if their view is directed low enough. The players don't see each other

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the first armor stand doesn't get replaced by the second one when the same location is used?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it won't be replaced

@@ -191,6 +195,15 @@ private void processJoinSync(Player player, boolean isAuthAvailable) {
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
}

if (service.getProperty(RestrictionSettings.SPECTATE_STAND_LOGIN)) {
// The delay is necessary in order to make sure that the player is teleported to spawn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+ doesn't the armor stand have to be deleted if the player disconnects as well?

ArmorStand stand = spawnStand(location);

armorStands.put(player, stand);
gameModeMap.put(player, player.getGameMode());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the server shuts down while players are not logged in? I guess they'll be saved with the spectator game mode, and next time when they'll join, they'll already have spectator game mode and won't be able to leave it. I think this is quite relevant because it's not only an inconvenience to a player, it's giving them access to a game mode that many servers don't want to give to players...
I could imagine trying to make use of the limbo player stuff or to maybe have an additional setting that will set players to survival instead of spectator when the code would want to. It's ugly but we've had to add a few of those failsafe properties in the past and people seem happy with it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently, when the plugin disabled, I can call a function that will remove all armorstands and return the players to their previous state. Is it possible to implement it this way?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please tell me if I can call SpectateLoginService in onDisable directly to remove armorstands, or is this not a good practice?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late reply.
I don't see any better way. I think you could get the SpecateLoginService with injector.getIfAvailable(SpectateLoginService.class) in AuthMe#onDisable. But still, when a server unexpectedly shuts down (if it crashes or its process is terminated abruptly) we have the problem that players are potentially in spectator mode, and there are armor stands that no one tracks anymore. I don't know if the armor stands are an issue (I have zero experience with the way you spawn them).
Wondering if we should have a property that specifies what game mode a player should change to if after authentication, we would put him into spectate game mode and/or to add the game mode to the LimboPlayer. I can elaborate on the whole limbo player thing if it helps

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Untraceable armorstand is not as critical as players in Spectator gamemode. It would be really cool if it could be done with LimboPlayer

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about adding a "limboArmorStandUUID" field to LimboPlayer?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean adding a way to keep track of whether a player is assigned an armorstand?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrchefran yes, exactly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants