-
Notifications
You must be signed in to change notification settings - Fork 297
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
RFC: Teleport to players' last locations in worlds #1794
Conversation
|
} | ||
if (yc != null) { | ||
try { | ||
if (! yc.isSet("schema")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YamlConfiguration should have like getInteger() for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ha! Yes, I see that now. When I first looked at the docs for YamlConfiguration, I didn't realize that the list of methods was not in alphabetic order. I stopped when I saw the .get and .isSet methods and no other .get or .is methods. I've refactored to use the .isInt, .isDouble, .getInt, and .getDouble methods. Thanks for the tip!
yc = null; | ||
// fall through to use world spawn location | ||
} | ||
if (yc != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been a while since I've looked at MV's code but I think we have a simpler way to serialize/deserialize location data.
* | ||
* @return A non-null MVDestination | ||
*/ | ||
public MVDestination getDestination(String destination) { | ||
public MVDestination getDestination(String destination, Player player) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better you leave the old method in just add this as a new method. This way we can preserve backwards compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look a little later in the diff, you'll see that's what I already did. I didn't want to break the existing API. The original method is just a shim that supports the original API. It simply calls the new API with null for player and the behavior is the same as the old behavior and still keeps the code DRY.
Having the ability to enable/disable this on a per-player basis is a good idea. It allows for more use cases than my simple case which I had not thought of. I think that using the permissions system might be a good way to handle how to enable/disable for each player. I think that's what you were suggesting, as well (yes?). I still think there will need to be a global default enable/disable item, otherwise I don't think my use case is achievable (unless I misunderstand what you're meaning). My use case is to specifically allow this behavior for all users without having to enable it for each new player that comes along. Having the global setting and then per-user permissions allows for both whitelisting and blacklisting use cases. Out of the box, it would be in whitelisting mode so as to retain backward compatibility. |
If you use only permissions (white list as you say) rather than also having a configuration value you can just give your default user the permission in your permission manager. Even better, if you want it for everyone no questions you can set it to |
I think my confusion comes from not having studied MV's permissions model, thus far. Now that I've started to look at it, I think it's starting to make sense, but I need to do so more exploration on how the permissions all work together. To that end, I have a question: If a player has |
Yes, you have that right. |
Now that I understand how the permissions all work, I understand what you meant about using permissions rather than needing a global configuration item. It's a great idea! I've got that all sorted out and implemented now. I think I've now taken care of all the outstanding items. There are three new permissions used:
The first two are used to control who can use the new last location destination functionality. The If a player has either I think I have this all ready to be a real PR. Can this code be merged? P.S. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice overall. There's still a few things that need addressing before we can merge.
@@ -258,6 +260,8 @@ public void onLoad() { | |||
// Setup our SafeTTeleporter | |||
this.safeTTeleporter = new SimpleSafeTTeleporter(this); | |||
this.unsafeCallWrapper = new UnsafeCallWrapper(this); | |||
// Set up MVPlayerLocation | |||
MVPlayerLocation.init(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way we can avoid static initialization like this?
} | ||
|
||
player = (Player) e; | ||
this.location = MVPlayerLocation.getPlayerLastLocation(player, world); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this location be set in setDestination using a non static method? Such as plugin.getPlayerLocationManager().getPlayerLastLocation...
or something. Just trying to avoid static stuff like this.
this.plugin.removePlayerSession(event.getPlayer()); | ||
Player player = event.getPlayer(); | ||
if (this.plugin.getMVPerms().hasPermission(player, "multiverse.teleport.self." | ||
+ LastLocationDestination.getID(), true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Theoretically the third arg here should be false, but it isn't used anymore so I guess it doesn't matter.
* This method is called when a player teleports anywhere. | ||
* @param event The Event that was fired. | ||
*/ | ||
@EventHandler(priority = EventPriority.MONITOR) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add an ignoreCancelled = true
here.
@@ -315,7 +339,9 @@ private void sendPlayerToDefaultWorld(final Player player) { | |||
new Runnable() { | |||
@Override | |||
public void run() { | |||
player.teleport(plugin.getMVWorldManager().getFirstSpawnWorld().getSpawnLocation()); | |||
LastLocationDestination destination = new LastLocationDestination(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are there no permission checks here?
} | ||
|
||
try { | ||
yc.save(new File(dir, playerID + ".yaml")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extension should be .yml
. Again, I think you could cut down on files by just having 1 file per player.
playerID = player.getUniqueId().toString(); | ||
|
||
file = new File(plugin.getDataFolder(), PLAYER_LOCATION_DATA | ||
+ File.separator + world.getName() + File.separator + playerID + ".yaml"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.yml
} | ||
|
||
public static void savePlayerLocation(Player player, Location location, String action) { | ||
String world = location.getWorld().getName(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use World UUID rather than name. Also, I might suggest just having 1 file for each player (again using UUID) with all world data stored in it.
plugin = p; | ||
} | ||
|
||
private static class InvalidData extends Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exceptions should be follow the naming scheme SuchAndSuchException. Also, make sure there's not an existing exception in Java that might cover this case well enough.
try { | ||
if (! yc.isSet("schema")) | ||
throw new InvalidData("missing schema node"); | ||
if (! yc.isInt("schema")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isInt
being true implies isSet
is true. No need for both.
Also, consider squashing your commits. |
I vote for this Pull request! |
@Tzzzt123 Same here. Been trying to find a fix here on GH and see this. Would love for this to be a feature. Would help a lot. |
No need to really "vote" for this PR. @dumptruckman performed a review but
@qwylz has not yet responded.
tldr: It will be merged but some housekeeping needs to happen first.
…On Sun, Apr 16, 2017 at 1:08 PM, Iliyan D. ***@***.***> wrote:
@Tzzzt123 <https://github.com/Tzzzt123> Same here. Been trying to find a
fix here on GH and see this. Would love for this to be a feature. Would
help a lot.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#1794 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEca5iHaQo5Ts3bm0PEhqJuvPTiExirks5rwmcUgaJpZM4L0XLY>
.
|
3 years later |
So how exactly do we enable this then? |
https://github.com/Taronyuu/StayPut is almost what you'd want, except it doesn't choose the default spawn location when there's no previous location in the database. |
Any news? |
Stay put |
Anything happening? |
I don't think so |
Stumbled across this PR while looking for how to preserve last location. Add all the worlds to a "share" with the |
Didn't read fully, but this looks like a feature of Multiverse-Inventories. |
outdated PR |
First, thank you for the great plugin. Recently I tested several plugins for managing multiple worlds and Multiverse-Core handily came out on top. Thank you!
Secondly, this is not actually a request to merge code at this time--this code is definitely not ready to be merged. I've submitted this PR more as an early request for comments and guidance as I work to get the code ready for a real pull request. Will you please read through this submission and the accompanying code and provide any suggestions and guidance necessary for me to get this ready for a true pull request?
This code is intended to add a new, non-default feature to Multiverse-Core. When enabled, the feature makes it so that when a player leaves a world, his/her last position in the world is saved. Then, when teleporting back to the world using the teleport syntax of just the bare world name (i.e. no "w:" or "e:" prefix), the player is teleported to his/her previously saved location in the world rather than to the world's spawn point. If the player has no saved location for the world, or if the save cannot be read/parsed for some reason, the player is teleported to the world's spawn point as a fallback measure. The behavior when using the "w:" or "e:" syntaxes is unchanged (i.e. always teleports to the world's spawn location or an exact location, respectively).
In it's current form, the code works, but is in an hackish, "can I even get this to work" kind of state. I need to take care of the following items before it's really ready for a true pull request:
Currently, it's not possible to disable the feature. I still need to add a configuration property for the plugin that will control whether the feature is enabled or disabled. I plan to have it default to being disabled, so that, by default, there is no change in behavior.
The code is currently embedded in several different classes. Very ugly. I need to refactor the code into it's own class(es) (and an exception) which will be utilized by the various listener and command classes.
I haven't done anything about permissions, yet. There should probably be separate permissions for teleporting to a world at the player's saved location versus teleporting to the world's spawn point or exact locations.
The code currently saves a players location in a world when leaving a world either via teleporting or the player quitting. It does not save players' locations when the server is stopped. I'm not sure how to listen for that. Is there a bukkit event? A player's location is also not saved when he/she is kicked from a world. I figure that if someone is misbehaving enough to be kicked, his/her location doesn't need to be save (however, if there was a previously saved location for the player, that saved information is not deleted).
While my day job is software development, my experience is in other languages. I've never written a line of Java until writing the code for this feature yesterday. Hopefully, I haven't abused Java too badly, and there's likely more Java-like ways to do some of what this code does. Suggestions are welcome, please.
One final note: I have developed this code under Oracle's official Java 8 JDK. Hopefully, I haven't used any constructs or patterns that cause problems on earlier versions or other flavors of Java.
Again, thank you for the great plugin. I hope that I can get the code for this feature in order so that it can be merged. Please let me know of any guidance and suggestions that you have.