Skip to content

Commit a630e31

Browse files
authored
Merge pull request #624 from Multiverse/feat/validate-bed-anchor
Add exist validation for bed and anchor respawn location during share handling
2 parents a85eb91 + 3fa82df commit a630e31

File tree

9 files changed

+356
-13
lines changed

9 files changed

+356
-13
lines changed

src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ public Try<Void> setUseImprovedRespawnLocationDetection(boolean useImprovedRespa
152152
return this.configHandle.set(configNodes.useImprovedRespawnLocationDetection, useImprovedRespawnLocationDetection);
153153
}
154154

155+
@ApiStatus.AvailableSince("5.2")
156+
public boolean getValidateBedAnchorRespawnLocation() {
157+
return this.configHandle.get(configNodes.validateBedAnchorRespawnLocation);
158+
}
159+
160+
@ApiStatus.AvailableSince("5.2")
161+
public Try<Void> setValidateBedAnchorRespawnLocation(boolean validateBedAnchorRespawnLocation) {
162+
return this.configHandle.set(configNodes.validateBedAnchorRespawnLocation, validateBedAnchorRespawnLocation);
163+
}
164+
155165
public boolean getResetLastLocationOnDeath() {
156166
return this.configHandle.get(configNodes.resetLastLocationOnDeath);
157167
}

src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfigNodes.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ public Object serialize(Shares sharables, Class<Shares> aClass) {
119119
.name("use-improved-respawn-location-detection")
120120
.build());
121121

122+
final ConfigNode<Boolean> validateBedAnchorRespawnLocation = node(ConfigNode.builder("sharables.validate-bed-anchor-respawn-location", Boolean.class)
123+
.comment("")
124+
.comment("When enabled, we will validate the bed/anchor respawn location on group/world change.")
125+
.comment("The validation checks if the bed/anchor block still exists at the saved location and is usable.")
126+
.comment("When the validation fails, the respawn location will be cleared and default world spawn will be used instead.")
127+
.comment("Disable this if you don't want validation, or you want another plugin to handle respawn logic.")
128+
.defaultValue(true)
129+
.name("validate-bed-anchor-respawn-location")
130+
.build());
131+
122132
final ConfigNode<Boolean> resetLastLocationOnDeath = node(ConfigNode.builder("sharables.reset-last-location-on-death", Boolean.class)
123133
.comment("")
124134
.comment("When set to true, the last location of the player will be reset when they die.")

src/main/java/org/mvplugins/multiverse/inventories/listeners/SpawnChangeListener.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.mvplugins.multiverse.inventories.MultiverseInventories;
1515
import org.mvplugins.multiverse.inventories.handleshare.SingleShareWriter;
1616
import org.mvplugins.multiverse.inventories.share.Sharables;
17+
import org.mvplugins.multiverse.inventories.util.RespawnLocation;
1718

1819
import static org.mvplugins.multiverse.inventories.util.MinecraftTools.findAnchorFromRespawnLocation;
1920
import static org.mvplugins.multiverse.inventories.util.MinecraftTools.findBedFromRespawnLocation;
@@ -41,15 +42,26 @@ public void onEvent(PlayerSetSpawnEvent event) {
4142
return;
4243
}
4344
Player player = event.getPlayer();
45+
Location newSpawnLoc = event.getLocation();
46+
if (newSpawnLoc == null) {
47+
updatePlayerSpawn(player, null);
48+
return;
49+
}
4450
if (event.getCause() == PlayerSetSpawnEvent.Cause.BED) {
45-
updatePlayerSpawn(player, findBedFromRespawnLocation(event.getLocation()));
51+
updatePlayerSpawn(player, new RespawnLocation(
52+
findBedFromRespawnLocation(newSpawnLoc),
53+
RespawnLocation.RespawnLocationType.BED
54+
));
4655
return;
4756
}
4857
if (event.getCause() == PlayerSetSpawnEvent.Cause.RESPAWN_ANCHOR) {
49-
updatePlayerSpawn(player, findAnchorFromRespawnLocation(event.getLocation()));
58+
updatePlayerSpawn(player, new RespawnLocation(
59+
findAnchorFromRespawnLocation(newSpawnLoc),
60+
RespawnLocation.RespawnLocationType.ANCHOR
61+
));
5062
return;
5163
}
52-
updatePlayerSpawn(player, event.getLocation());
64+
updatePlayerSpawn(player, new RespawnLocation(newSpawnLoc, RespawnLocation.RespawnLocationType.UNKNOWN));
5365
}
5466
};
5567
}
@@ -66,12 +78,19 @@ public void onEvent(PlayerSpawnChangeEvent event) {
6678
return;
6779
}
6880
Player player = event.getPlayer();
81+
Location newSpawnLoc = event.getNewSpawn();
6982
if (event.getCause() == PlayerSpawnChangeEvent.Cause.BED) {
70-
updatePlayerSpawn(player, findBedFromRespawnLocation(event.getNewSpawn()));
83+
updatePlayerSpawn(player, new RespawnLocation(
84+
findBedFromRespawnLocation(newSpawnLoc),
85+
RespawnLocation.RespawnLocationType.BED
86+
));
7187
return;
7288
}
7389
if (event.getCause() == PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR) {
74-
updatePlayerSpawn(player, findAnchorFromRespawnLocation(event.getNewSpawn()));
90+
updatePlayerSpawn(player, new RespawnLocation(
91+
findAnchorFromRespawnLocation(newSpawnLoc),
92+
RespawnLocation.RespawnLocationType.ANCHOR
93+
));
7594
return;
7695
}
7796
updatePlayerSpawn(player, event.getNewSpawn());

src/main/java/org/mvplugins/multiverse/inventories/share/LocationSerializer.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
import org.bukkit.Location;
44
import org.mvplugins.multiverse.core.world.location.UnloadedWorldLocation;
55
import org.mvplugins.multiverse.inventories.util.LegacyParsers;
6+
import org.mvplugins.multiverse.inventories.util.RespawnLocation;
67

78
import java.util.Map;
89

910
/**
1011
* A simple {@link SharableSerializer} usable with {@link Location} which converts the {@link Location} to the string
1112
* format that is used by default in Multiverse-Inventories.
12-
* @deprecated Locations no longer need a special serializer because they are
13-
* {@link org.bukkit.configuration.serialization.ConfigurationSerializable}. This remains to convert legacy data.
1413
*/
15-
@Deprecated
16-
final class LocationSerializer implements SharableSerializer<Location> {
14+
abstract class LocationSerializer implements SharableSerializer<Location> {
1715

1816
@Override
1917
public Location deserialize(Object obj) {
@@ -30,7 +28,25 @@ public Location deserialize(Object obj) {
3028
}
3129

3230
@Override
33-
public Object serialize(Location location) {
34-
return new UnloadedWorldLocation(location);
31+
abstract public Location serialize(Location loc);
32+
33+
static final class UnloadedWorldLocationSerializer extends LocationSerializer {
34+
@Override
35+
public Location serialize(Location loc) {
36+
if (loc != null && !(loc instanceof UnloadedWorldLocation)) {
37+
return new UnloadedWorldLocation(loc);
38+
}
39+
return loc;
40+
}
41+
}
42+
43+
static final class RespawnLocationSerializer extends LocationSerializer {
44+
@Override
45+
public Location serialize(Location loc) {
46+
if (loc != null && !(loc instanceof RespawnLocation)) {
47+
return new RespawnLocation(loc, RespawnLocation.RespawnLocationType.UNKNOWN);
48+
}
49+
return loc;
50+
}
3551
}
3652
}

src/main/java/org/mvplugins/multiverse/inventories/share/Sharables.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.bukkit.entity.Player;
3232
import org.bukkit.inventory.ItemStack;
3333
import org.bukkit.potion.PotionEffect;
34+
import org.mvplugins.multiverse.inventories.util.RespawnLocation;
3435

3536
import java.util.ArrayList;
3637
import java.util.Arrays;
@@ -618,11 +619,19 @@ public boolean updatePlayer(Player player, ProfileData profile) {
618619
setSpawnLocation(player, player.getWorld().getSpawnLocation());
619620
return false;
620621
}
622+
if (inventoriesConfig.getValidateBedAnchorRespawnLocation()
623+
&& loc instanceof RespawnLocation respawnLocation
624+
&& !respawnLocation.isValidRespawnLocation()) {
625+
Logging.finer("Respawn location validation failed for respawn type: " + respawnLocation.getRespawnType());
626+
setSpawnLocation(player, player.getWorld().getSpawnLocation());
627+
return false;
628+
}
621629
setSpawnLocation(player, loc);
622630
Logging.finer("updated respawn location: " + player.getBedSpawnLocation());
623631
return true;
624632
}
625-
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_BED_SPAWN_LOCATION), new LocationSerializer())
633+
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_BED_SPAWN_LOCATION),
634+
new LocationSerializer.RespawnLocationSerializer())
626635
.altName("bedspawn").altName("bed").altName("beds").altName("bedspawns").build();
627636

628637
// todo: handle this somewhere better
@@ -661,7 +670,8 @@ public boolean updatePlayer(Player player, ProfileData profile) {
661670
safetyTeleporter.to(loc).checkSafety(false).teleportSingle(player);
662671
return true;
663672
}
664-
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_LAST_LOCATION), new LocationSerializer())
673+
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_LAST_LOCATION),
674+
new LocationSerializer.UnloadedWorldLocationSerializer())
665675
.altName("loc").altName("location").altName("pos").altName("position").optional().build();
666676

667677
/**

src/main/java/org/mvplugins/multiverse/inventories/util/MinecraftTools.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.bukkit.block.data.type.Bed;
77
import org.bukkit.block.data.type.RespawnAnchor;
88
import org.bukkit.inventory.ItemStack;
9+
import org.jetbrains.annotations.Contract;
910

1011
import javax.annotation.Nullable;
1112

@@ -39,6 +40,7 @@ public static ItemStack[] fillWithAir(ItemStack[] items) {
3940
return items;
4041
}
4142

43+
@Contract("null -> null; !null -> !null")
4244
public static @Nullable Location findBedFromRespawnLocation(@Nullable Location respawnLocation) {
4345
if (respawnLocation == null) {
4446
return null;
@@ -60,6 +62,7 @@ public static ItemStack[] fillWithAir(ItemStack[] items) {
6062
return respawnLocation;
6163
}
6264

65+
@Contract("null -> null; !null -> !null")
6366
public static @Nullable Location findAnchorFromRespawnLocation(@Nullable Location respawnLocation) {
6467
if (respawnLocation == null) {
6568
return null;

0 commit comments

Comments
 (0)