Skip to content

Commit 1eca4cd

Browse files
committed
Add exist validation for bed and anchor respawn location during share handling
1 parent 2506dec commit 1eca4cd

File tree

9 files changed

+304
-13
lines changed

9 files changed

+304
-13
lines changed

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

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

155+
public boolean getValidateBedAnchorRespawnLocation() {
156+
return this.configHandle.get(configNodes.validateBedAnchorRespawnLocation);
157+
}
158+
159+
public Try<Void> setValidateBedAnchorRespawnLocation(boolean validateBedAnchorRespawnLocation) {
160+
return this.configHandle.set(configNodes.validateBedAnchorRespawnLocation, validateBedAnchorRespawnLocation);
161+
}
162+
155163
public boolean getResetLastLocationOnDeath() {
156164
return this.configHandle.get(configNodes.resetLastLocationOnDeath);
157165
}

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

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

121+
final ConfigNode<Boolean> validateBedAnchorRespawnLocation = node(ConfigNode.builder("sharables.validate-bed-anchor-respawn-location", Boolean.class)
122+
.comment("")
123+
.comment("When enabled, we will validate the bed/anchor respawn location on group/world change.")
124+
.comment("The validation checks if the bed/anchor block still exists at the saved location and is usable.")
125+
.comment("When the validation fails, the respawn location will be cleared and default world spawn will be used instead.")
126+
.comment("Disable this if you don't want validation, or you want another plugin to handle respawn logic.")
127+
.defaultValue(true)
128+
.name("validate-bed-anchor-respawn-location")
129+
.build());
130+
121131
final ConfigNode<Boolean> resetLastLocationOnDeath = node(ConfigNode.builder("sharables.reset-last-location-on-death", Boolean.class)
122132
.comment("")
123133
.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
}
@@ -65,12 +77,19 @@ public void onEvent(PlayerSpawnChangeEvent event) {
6577
return;
6678
}
6779
Player player = event.getPlayer();
80+
Location newSpawnLoc = event.getNewSpawn();
6881
if (event.getCause() == PlayerSpawnChangeEvent.Cause.BED) {
69-
updatePlayerSpawn(player, findBedFromRespawnLocation(event.getNewSpawn()));
82+
updatePlayerSpawn(player, new RespawnLocation(
83+
findBedFromRespawnLocation(newSpawnLoc),
84+
RespawnLocation.RespawnLocationType.BED
85+
));
7086
return;
7187
}
7288
if (event.getCause() == PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR) {
73-
updatePlayerSpawn(player, findAnchorFromRespawnLocation(event.getNewSpawn()));
89+
updatePlayerSpawn(player, new RespawnLocation(
90+
findAnchorFromRespawnLocation(newSpawnLoc),
91+
RespawnLocation.RespawnLocationType.ANCHOR
92+
));
7493
return;
7594
}
7695
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
@@ -30,6 +30,7 @@
3030
import org.bukkit.entity.Player;
3131
import org.bukkit.inventory.ItemStack;
3232
import org.bukkit.potion.PotionEffect;
33+
import org.mvplugins.multiverse.inventories.util.RespawnLocation;
3334

3435
import java.util.ArrayList;
3536
import java.util.Arrays;
@@ -612,11 +613,19 @@ public boolean updatePlayer(Player player, ProfileData profile) {
612613
setSpawnLocation(player, player.getWorld().getSpawnLocation());
613614
return false;
614615
}
616+
if (inventoriesConfig.getValidateBedAnchorRespawnLocation()
617+
&& loc instanceof RespawnLocation respawnLocation
618+
&& !respawnLocation.isValidRespawnLocation()) {
619+
Logging.finer("Respawn location validation failed for respawn type: " + respawnLocation.getRespawnType());
620+
setSpawnLocation(player, player.getWorld().getSpawnLocation());
621+
return false;
622+
}
615623
setSpawnLocation(player, loc);
616624
Logging.finer("updated respawn location: " + player.getBedSpawnLocation());
617625
return true;
618626
}
619-
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_BED_SPAWN_LOCATION), new LocationSerializer())
627+
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_BED_SPAWN_LOCATION),
628+
new LocationSerializer.RespawnLocationSerializer())
620629
.altName("bedspawn").altName("bed").altName("beds").altName("bedspawns").build();
621630

622631
// todo: handle this somewhere better
@@ -655,7 +664,8 @@ public boolean updatePlayer(Player player, ProfileData profile) {
655664
safetyTeleporter.to(loc).checkSafety(false).teleport(player);
656665
return true;
657666
}
658-
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_LAST_LOCATION), new LocationSerializer())
667+
}).serializer(new ProfileEntry(false, DataStrings.PLAYER_LAST_LOCATION),
668+
new LocationSerializer.UnloadedWorldLocationSerializer())
659669
.altName("loc").altName("location").altName("pos").altName("position").optional().build();
660670

661671
/**

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)