Add config option to enable debug messages and return to overworld when sleeping on dreamlands.
Change PlayerStorage to save player current world to avoid desync and correct when player joins the world. This fixes the desync when joining the server after deleting the dreamlands world.
This commit is contained in:
parent
c7210ccb35
commit
7c4647dd53
5 changed files with 137 additions and 43 deletions
|
|
@ -2,48 +2,72 @@ package org.adrianvictor.sweetdreams;
|
||||||
|
|
||||||
import com.destroystokyo.paper.event.player.PlayerSetSpawnEvent;
|
import com.destroystokyo.paper.event.player.PlayerSetSpawnEvent;
|
||||||
|
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.bukkit.event.entity.EntityPortalEnterEvent;
|
import org.bukkit.event.entity.EntityPortalEnterEvent;
|
||||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
import org.bukkit.event.player.PlayerBedEnterEvent;
|
import org.bukkit.event.player.PlayerBedEnterEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class EventListener implements Listener {
|
public class EventListener implements Listener {
|
||||||
private final PlayerStorage storage;
|
private final PlayerStorage storage;
|
||||||
private final PlayerTeleporter tp;
|
private final PlayerTeleporter tp;
|
||||||
private final YamlConfiguration configuration;
|
private final YamlConfiguration configuration;
|
||||||
|
private final World dreamlands;
|
||||||
|
private final SweetDreams plugin;
|
||||||
|
|
||||||
public EventListener() {
|
public EventListener() {
|
||||||
this.storage = SweetDreams.getPlugin().getStorage();
|
this.storage = SweetDreams.getPlugin().getStorage();
|
||||||
this.tp = new PlayerTeleporter();
|
this.tp = new PlayerTeleporter();
|
||||||
this.configuration = SweetDreams.getPlugin().getConfiguration().getPluginConfig();
|
this.configuration = SweetDreams.getPlugin().getConfiguration().getPluginConfig();
|
||||||
|
this.dreamlands = SweetDreams.getPlugin().getWorld();
|
||||||
|
this.plugin = SweetDreams.getPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerBedEnterEvent(PlayerBedEnterEvent event) {
|
public void onPlayerBedEnterEvent(PlayerBedEnterEvent event) {
|
||||||
if (event.getPlayer().getWorld() == SweetDreams.getPlugin().getWorld()) {
|
long time = event.getPlayer().getWorld().getTime();
|
||||||
storage.savePlayerSpawnPoint(event.getPlayer());
|
|
||||||
event.getPlayer().sendMessage("Respawn point set.");
|
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Long time = event.getPlayer().getWorld().getTime();
|
|
||||||
|
|
||||||
if (!(time >= 13000 && time <= 23000)) {
|
if (!(time >= 13000 && time <= 23000)) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tp.teleport(event.getPlayer(), false);
|
tp.teleport(event.getPlayer(), false, "You feel free...", Sound.BLOCK_BEACON_ACTIVATE);
|
||||||
|
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInteract(PlayerInteractEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
Block type = event.getClickedBlock();
|
||||||
|
|
||||||
|
if (event.getAction() != Action.LEFT_CLICK_BLOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (player.getWorld() != dreamlands || type == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (type.getType().name().endsWith("_BED")) {
|
||||||
|
storage.savePlayerSpawnPoint(event.getPlayer());
|
||||||
|
event.getPlayer().sendMessage("Respawn point set.");
|
||||||
|
tp.teleport(event.getPlayer(), false, "Maybe you'll return to this dream....", Sound.BLOCK_BEACON_DEACTIVATE);
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerSetSpawn(PlayerSetSpawnEvent event) {
|
public void onPlayerSetSpawn(PlayerSetSpawnEvent event) {
|
||||||
if (event.getPlayer().getWorld() != SweetDreams.getPlugin().getWorld())
|
if (event.getPlayer().getWorld() != SweetDreams.getPlugin().getWorld())
|
||||||
|
|
@ -80,4 +104,27 @@ public class EventListener implements Listener {
|
||||||
tp.teleport(player, true);
|
tp.teleport(player, true);
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
|
UUID uuid = event.getPlayer().getUniqueId();
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
PlayerStorage.StorageWorldType actualWorld = storage.getActualWorld(player);
|
||||||
|
plugin.sendDebugMessage(
|
||||||
|
"Player %s logged in on %s with inventory from %s. (flag: %s, world: %s)"
|
||||||
|
.formatted(player.getName(), player.getWorld().getName(), actualWorld.getKey(), storage.getFlag(player).getKey(), actualWorld.getKey())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (storage.exists(uuid) && storage.getFlag(player) != actualWorld) {
|
||||||
|
plugin.getLogger().warning(
|
||||||
|
"Player %s was desynced! Changing inventory back to %s."
|
||||||
|
.formatted(player.getName(), actualWorld.getKey())
|
||||||
|
);
|
||||||
|
|
||||||
|
storage.loadPlayer(player, actualWorld);
|
||||||
|
player.sendMessage("Your dream ended prematurely...");
|
||||||
|
player.playSound(player.getLocation(), Sound.BLOCK_BEACON_DEACTIVATE, 1.0f, 1.0f);
|
||||||
|
player.teleport(Objects.requireNonNullElse(player.getRespawnLocation(), actualWorld.getWorld().getSpawnLocation()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,23 @@
|
||||||
package org.adrianvictor.sweetdreams;
|
package org.adrianvictor.sweetdreams;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PlayerStorage {
|
public class PlayerStorage {
|
||||||
private final Configuration config;
|
private final Configuration configuration;
|
||||||
|
private final YamlConfiguration config;
|
||||||
private final YamlConfiguration storage;
|
private final YamlConfiguration storage;
|
||||||
|
private final NamespacedKey worldFlagKey = new NamespacedKey(SweetDreams.getPlugin(), "world_flag");
|
||||||
|
private final World overworld;
|
||||||
|
private final World skylands;
|
||||||
// Map<UUID, ItemStack[]> inventories = new HashMap<>();
|
// Map<UUID, ItemStack[]> inventories = new HashMap<>();
|
||||||
|
|
||||||
public enum StorageWorldType {
|
public enum StorageWorldType {
|
||||||
|
|
@ -25,11 +33,22 @@ public class PlayerStorage {
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
if (this.getKey().equals("overworld")) {
|
||||||
|
return Bukkit.getWorld(SweetDreams.getPlugin().getConfiguration().getPluginConfig().getString("defaultWorld", "world"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SweetDreams.getPlugin().getWorld();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerStorage(Configuration config) {
|
public PlayerStorage(Configuration config) {
|
||||||
this.config = config;
|
this.configuration = config;
|
||||||
this.storage = config.getPlayerStorage();
|
this.storage = config.getPlayerStorage();
|
||||||
|
this.config = config.getPluginConfig();
|
||||||
|
this.overworld = Bukkit.getWorld(this.config.getString("defaultWorld", "world"));
|
||||||
|
this.skylands = SweetDreams.getPlugin().getWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void savePlayer(Player player, StorageWorldType type) {
|
public void savePlayer(Player player, StorageWorldType type) {
|
||||||
|
|
@ -64,7 +83,7 @@ public class PlayerStorage {
|
||||||
storage.set(base + ".stats.food", player.getFoodLevel());
|
storage.set(base + ".stats.food", player.getFoodLevel());
|
||||||
storage.set(base + ".stats.saturation", player.getSaturation());
|
storage.set(base + ".stats.saturation", player.getSaturation());
|
||||||
|
|
||||||
config.savePlayerStorage();
|
configuration.savePlayerStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Location loadPlayer(Player player, StorageWorldType type) {
|
public Location loadPlayer(Player player, StorageWorldType type) {
|
||||||
|
|
@ -124,6 +143,15 @@ public class PlayerStorage {
|
||||||
player.setFoodLevel(storage.getInt(base + ".stats.food", 20));
|
player.setFoodLevel(storage.getInt(base + ".stats.food", 20));
|
||||||
player.setSaturation((float) storage.getDouble(base + ".stats.saturation", 5.0));
|
player.setSaturation((float) storage.getDouble(base + ".stats.saturation", 5.0));
|
||||||
|
|
||||||
|
storage.set("players." + uuid + ".worldFlag", type.name());
|
||||||
|
player.getPersistentDataContainer().set(
|
||||||
|
worldFlagKey,
|
||||||
|
PersistentDataType.STRING,
|
||||||
|
type.name()
|
||||||
|
);
|
||||||
|
|
||||||
|
configuration.savePlayerStorage();
|
||||||
|
|
||||||
Object rawSpawn = storage.get(base + ".spawn");
|
Object rawSpawn = storage.get(base + ".spawn");
|
||||||
if (rawSpawn instanceof Location spawn) {
|
if (rawSpawn instanceof Location spawn) {
|
||||||
return spawn;
|
return spawn;
|
||||||
|
|
@ -132,6 +160,27 @@ public class PlayerStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean exists(UUID uuid) {
|
||||||
|
String base = "players." + uuid;
|
||||||
|
return storage.contains(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageWorldType getFlag(Player player) {
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
String worldFlag = storage.getString("players." + uuid + ".worldFlag", null);
|
||||||
|
|
||||||
|
if (worldFlag == null) {
|
||||||
|
worldFlag = player.getPersistentDataContainer().get(worldFlagKey, PersistentDataType.STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StorageWorldType.valueOf(worldFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageWorldType getActualWorld(Player player) {
|
||||||
|
return player.getWorld() == SweetDreams.getPlugin().getWorld() ?
|
||||||
|
StorageWorldType.SKYLANDS : StorageWorldType.OVERWORLD;
|
||||||
|
}
|
||||||
|
|
||||||
public void savePlayerSpawnPoint(Player player) {
|
public void savePlayerSpawnPoint(Player player) {
|
||||||
UUID uuid = player.getUniqueId();
|
UUID uuid = player.getUniqueId();
|
||||||
String base = "players." + uuid + ".skylands";
|
String base = "players." + uuid + ".skylands";
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,9 @@ public class PlayerTeleporter {
|
||||||
private final Set<UUID> teleporting = new HashSet<>();
|
private final Set<UUID> teleporting = new HashSet<>();
|
||||||
private final PlayerStorage storage = SweetDreams.getPlugin().getStorage();
|
private final PlayerStorage storage = SweetDreams.getPlugin().getStorage();
|
||||||
|
|
||||||
public void teleport(Player player, boolean bad) {
|
public void teleport(Player player, boolean bad, String message, Sound sound) {
|
||||||
UUID uuid = player.getUniqueId();
|
UUID uuid = player.getUniqueId();
|
||||||
Sound sound = bad ? Sound.ENTITY_ENDERMAN_SCREAM : Sound.ENTITY_PLAYER_LEVELUP;
|
|
||||||
YamlConfiguration configuration = SweetDreams.getPlugin().getConfiguration().getPluginConfig();
|
YamlConfiguration configuration = SweetDreams.getPlugin().getConfiguration().getPluginConfig();
|
||||||
String message = bad ? "You woke up from a bad dream..." : "You woke up!";
|
|
||||||
boolean clearInventory = (bad && configuration.getBoolean("keepInventory", true));
|
boolean clearInventory = (bad && configuration.getBoolean("keepInventory", true));
|
||||||
|
|
||||||
if (!teleporting.add(uuid)) return;
|
if (!teleporting.add(uuid)) return;
|
||||||
|
|
@ -50,6 +48,13 @@ public class PlayerTeleporter {
|
||||||
player.playSound(player.getLocation(), sound, 1.0f, 1.0f);
|
player.playSound(player.getLocation(), sound, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (configuration.getBoolean("sendMessageOnWakeUp", true)) {
|
||||||
|
player.sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configuration.getBoolean("playSoundOnWakeUp", true)) {
|
||||||
|
player.playSound(player.getLocation(), sound, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
switchInventories(player, PlayerStorage.StorageWorldType.OVERWORLD, PlayerStorage.StorageWorldType.SKYLANDS);
|
switchInventories(player, PlayerStorage.StorageWorldType.OVERWORLD, PlayerStorage.StorageWorldType.SKYLANDS);
|
||||||
player.teleport(storage.loadPlayer(player, PlayerStorage.StorageWorldType.SKYLANDS));
|
player.teleport(storage.loadPlayer(player, PlayerStorage.StorageWorldType.SKYLANDS));
|
||||||
}
|
}
|
||||||
|
|
@ -59,6 +64,12 @@ public class PlayerTeleporter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void teleport(Player player, boolean bad) {
|
||||||
|
String message = bad ? "You woke up from a bad dream..." : "You woke up!";
|
||||||
|
Sound sound = bad ? Sound.ENTITY_ENDERMAN_SCREAM : Sound.ENTITY_PLAYER_LEVELUP;
|
||||||
|
teleport(player, bad, message, sound);
|
||||||
|
}
|
||||||
|
|
||||||
private void switchInventories(Player player, PlayerStorage.StorageWorldType from, PlayerStorage.StorageWorldType to) {
|
private void switchInventories(Player player, PlayerStorage.StorageWorldType from, PlayerStorage.StorageWorldType to) {
|
||||||
storage.savePlayer(player, from);
|
storage.savePlayer(player, from);
|
||||||
player.getInventory().clear();
|
player.getInventory().clear();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
package org.adrianvictor.sweetdreams;
|
package org.adrianvictor.sweetdreams;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.WorldCreator;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
@ -17,40 +20,15 @@ public final class SweetDreams extends JavaPlugin {
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
plugin = this;
|
plugin = this;
|
||||||
configuration = new Configuration();
|
configuration = new Configuration();
|
||||||
|
String worldName = configuration.getPluginConfig().getString("dreamlandsWorld", "world_sweetdreams");
|
||||||
storage = new PlayerStorage(configuration);
|
storage = new PlayerStorage(configuration);
|
||||||
|
world = createSkylandsWorld(worldName);
|
||||||
boolean generated = false;
|
|
||||||
|
|
||||||
for (World world: getServer().getWorlds()) {
|
|
||||||
if (world.getName().equals(
|
|
||||||
configuration.getPluginConfig().getString("dreamlandsWorld", "world_sweetdreams"))
|
|
||||||
) {
|
|
||||||
this.world = world;
|
|
||||||
generated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!generated) {
|
|
||||||
world = createSkylandsWorld("world_sweetdreams");
|
|
||||||
}
|
|
||||||
|
|
||||||
getServer().getPluginManager().registerEvents(new EventListener(), this);
|
getServer().getPluginManager().registerEvents(new EventListener(), this);
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskTimer(this, new KickerRunnable(), 20L, 20L);
|
Bukkit.getScheduler().runTaskTimer(this, new KickerRunnable(), 20L, 20L);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteFolder(File folder) {
|
|
||||||
if (folder.isDirectory()) {
|
|
||||||
File[] files = folder.listFiles();
|
|
||||||
if (files != null) {
|
|
||||||
for (File file : files) {
|
|
||||||
deleteFolder(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
folder.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
// Plugin shutdown logic
|
// Plugin shutdown logic
|
||||||
|
|
@ -82,4 +60,10 @@ public final class SweetDreams extends JavaPlugin {
|
||||||
public PlayerStorage getStorage() {
|
public PlayerStorage getStorage() {
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendDebugMessage(String message) {
|
||||||
|
if (configuration.getPluginConfig().getBoolean("debugMessages", false)) {
|
||||||
|
getLogger().info("[DEBUG] " + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ kickOnDayStart: true
|
||||||
playSoundOnWakeUp: true
|
playSoundOnWakeUp: true
|
||||||
sendMessageOnWakeUp: true
|
sendMessageOnWakeUp: true
|
||||||
keepInventory: true
|
keepInventory: true
|
||||||
|
sleepingOnDreamReturnsToOverworld: true
|
||||||
|
|
||||||
# Won't affect already generated chunks
|
# Won't affect already generated chunks
|
||||||
# /!\ Don't change unless you know what you're doing
|
# /!\ Don't change unless you know what you're doing
|
||||||
|
|
@ -25,4 +26,6 @@ worldGeneration:
|
||||||
treeMaxHeight: 3 # Max random number that will be ADDED to the minimum size
|
treeMaxHeight: 3 # Max random number that will be ADDED to the minimum size
|
||||||
treeMinHeight: 4
|
treeMinHeight: 4
|
||||||
oreMaxDepth: 20
|
oreMaxDepth: 20
|
||||||
dirtLayers: 3
|
dirtLayers: 3
|
||||||
|
|
||||||
|
debugMessages: false
|
||||||
Loading…
Add table
Add a link
Reference in a new issue