9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-27 18:49:11 +00:00

Events & API work, save DataSaveCauses as part of versioning

This commit is contained in:
William
2022-07-07 01:52:19 +01:00
parent fd08a3e7d0
commit 1c9d74f925
48 changed files with 1477 additions and 340 deletions

View File

@@ -15,6 +15,8 @@ import net.william278.husksync.data.JsonDataAdapter;
import net.william278.husksync.database.Database;
import net.william278.husksync.database.MySqlDatabase;
import net.william278.husksync.editor.DataEditor;
import net.william278.husksync.event.BukkitEventCannon;
import net.william278.husksync.event.EventCannon;
import net.william278.husksync.listener.BukkitEventListener;
import net.william278.husksync.listener.EventListener;
import net.william278.husksync.player.BukkitPlayer;
@@ -51,12 +53,18 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
private DataEditor dataEditor;
private EventCannon eventCannon;
private Settings settings;
private Locales locales;
private static BukkitHuskSync instance;
/**
* (<b>Internal use only)</b> Returns the instance of the implementing Bukkit plugin
*
* @return the instance of the Bukkit plugin
*/
public static BukkitHuskSync getInstance() {
return instance;
}
@@ -90,6 +98,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
getLoggingAdapter().log(Level.INFO, "Loading plugin configuration settings & locales...");
return reload().thenApply(loadedSettings -> {
if (loadedSettings) {
logger.showDebugLogs(settings.getBooleanValue(Settings.ConfigOption.DEBUG_LOGGING));
getLoggingAdapter().log(Level.INFO, "Successfully loaded plugin configuration settings & locales");
} else {
getLoggingAdapter().log(Level.SEVERE, "Failed to load plugin configuration settings and/or locales");
@@ -106,6 +115,12 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
}
}
return succeeded;
}).thenApply(succeeded -> {
// Prepare event cannon
if (succeeded) {
eventCannon = new BukkitEventCannon();
}
return succeeded;
}).thenApply(succeeded -> {
// Prepare data editor
if (succeeded) {
@@ -114,15 +129,14 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
return succeeded;
}).thenApply(succeeded -> {
// Establish connection to the database
this.database = new MySqlDatabase(settings, resourceReader, logger, dataAdapter);
if (succeeded) {
this.database = new MySqlDatabase(settings, resourceReader, logger, dataAdapter, eventCannon);
getLoggingAdapter().log(Level.INFO, "Attempting to establish connection to the database...");
final CompletableFuture<Boolean> databaseConnectFuture = new CompletableFuture<>();
Bukkit.getScheduler().runTask(this, () -> {
final boolean initialized = this.database.initialize();
if (!initialized) {
getLoggingAdapter().log(Level.SEVERE, "Failed to establish a connection to the database. "
+ "Please check the supplied database credentials in the config file");
getLoggingAdapter().log(Level.SEVERE, "Failed to establish a connection to the database. " + "Please check the supplied database credentials in the config file");
databaseConnectFuture.completeAsync(() -> false);
return;
}
@@ -134,13 +148,12 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
return false;
}).thenApply(succeeded -> {
// Establish connection to the Redis server
this.redisManager = new RedisManager(settings, dataAdapter);
if (succeeded) {
this.redisManager = new RedisManager(settings, dataAdapter, logger);
getLoggingAdapter().log(Level.INFO, "Attempting to establish connection to the Redis server...");
return this.redisManager.initialize().thenApply(initialized -> {
if (!initialized) {
getLoggingAdapter().log(Level.SEVERE, "Failed to establish a connection to the Redis server. "
+ "Please check the supplied Redis credentials in the config file");
getLoggingAdapter().log(Level.SEVERE, "Failed to establish a connection to the Redis server. " + "Please check the supplied Redis credentials in the config file");
return false;
}
getLoggingAdapter().log(Level.INFO, "Successfully established a connection to the Redis server");
@@ -178,7 +191,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
return succeeded;
}).thenApply(succeeded -> {
// Check for updates
if (settings.getBooleanValue(Settings.ConfigOption.CHECK_FOR_UPDATES) && succeeded) {
if (succeeded && settings.getBooleanValue(Settings.ConfigOption.CHECK_FOR_UPDATES)) {
getLoggingAdapter().log(Level.INFO, "Checking for updates...");
new UpdateChecker(getVersion(), getLoggingAdapter()).logToConsole();
}
@@ -186,8 +199,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
}).thenAccept(succeeded -> {
// Handle failed initialization
if (!succeeded) {
getLoggingAdapter().log(Level.SEVERE, "Failed to initialize HuskSync. " +
"The plugin will now be disabled");
getLoggingAdapter().log(Level.SEVERE, "Failed to initialize HuskSync. " + "The plugin will now be disabled");
getServer().getPluginManager().disablePlugin(this);
} else {
getLoggingAdapter().log(Level.INFO, "Successfully enabled HuskSync v" + getVersion());
@@ -237,6 +249,11 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
return dataEditor;
}
@Override
public @NotNull EventCannon getEventCannon() {
return eventCannon;
}
@Override
public @NotNull Settings getSettings() {
return settings;

View File

@@ -0,0 +1,125 @@
package net.william278.husksync.data;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
/**
* A mapped player inventory, providing methods to easily access a player's inventory.
*/
public class BukkitInventoryMap {
private ItemStack[] contents;
/**
* Creates a new mapped inventory from the given contents.
*
* @param contents the contents of the inventory
*/
protected BukkitInventoryMap(ItemStack[] contents) {
this.contents = contents;
}
/**
* Gets the contents of the inventory.
*
* @return the contents of the inventory
*/
public ItemStack[] getContents() {
return contents;
}
/**
* Set the contents of the inventory.
*
* @param contents the contents of the inventory
*/
public void setContents(ItemStack[] contents) {
this.contents = contents;
}
/**
* Gets the size of the inventory.
*
* @return the size of the inventory
*/
public int getSize() {
return contents.length;
}
/**
* Gets the item at the given index.
*
* @param index the index of the item to get
* @return the item at the given index
*/
public Optional<ItemStack> getItemAt(int index) {
if (contents.length >= index) {
if (contents[index] == null) {
return Optional.empty();
}
return Optional.of(contents[index]);
}
return Optional.empty();
}
/**
* Sets the item at the given index.
*
* @param itemStack the item to set at the given index
* @param index the index of the item to set
* @throws IllegalArgumentException if the index is out of bounds
*/
public void setItemAt(@NotNull ItemStack itemStack, int index) throws IllegalArgumentException {
contents[index] = itemStack;
}
/**
* Returns the main inventory contents.
*
* @return the main inventory contents
*/
public ItemStack[] getInventory() {
final ItemStack[] inventory = new ItemStack[36];
System.arraycopy(contents, 0, inventory, 0, Math.min(contents.length, inventory.length));
return inventory;
}
public ItemStack[] getHotbar() {
final ItemStack[] armor = new ItemStack[9];
for (int i = 0; i <= 9; i++) {
armor[i] = getItemAt(i).orElse(null);
}
return armor;
}
public Optional<ItemStack> getOffHand() {
return getItemAt(40);
}
public Optional<ItemStack> getHelmet() {
return getItemAt(39);
}
public Optional<ItemStack> getChestplate() {
return getItemAt(38);
}
public Optional<ItemStack> getLeggings() {
return getItemAt(37);
}
public Optional<ItemStack> getBoots() {
return getItemAt(36);
}
public ItemStack[] getArmor() {
final ItemStack[] armor = new ItemStack[4];
for (int i = 36; i < 40; i++) {
armor[i - 36] = getItemAt(i).orElse(null);
}
return armor;
}
}

View File

@@ -4,6 +4,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
@@ -21,7 +22,8 @@ public class BukkitSerializer {
* @param inventoryContents The contents of the inventory
* @return The serialized inventory contents
*/
public static CompletableFuture<String> serializeInventory(ItemStack[] inventoryContents) throws DataDeserializationException {
public static CompletableFuture<String> serializeItemStackArray(ItemStack[] inventoryContents)
throws DataDeserializationException {
return CompletableFuture.supplyAsync(() -> {
// Return an empty string if there is no inventory item data to serialize
if (inventoryContents.length == 0) {
@@ -49,20 +51,35 @@ public class BukkitSerializer {
}
/**
* Returns an array of ItemStacks from serialized inventory data. Note: empty slots will be represented by {@code null}
* Returns a {@link BukkitInventoryMap} from a serialized array of ItemStacks representing the contents of a player's inventory.
*
* @param inventoryData The serialized {@link ItemStack[]} array
* @return The inventory contents as an array of {@link ItemStack}s
* @param serializedPlayerInventory The serialized {@link ItemStack[]} inventory array
* @return The deserialized ItemStacks, mapped for convenience as a {@link BukkitInventoryMap}
* @throws DataDeserializationException If the serialized item stack array could not be deserialized
*/
public static CompletableFuture<ItemStack[]> deserializeInventory(String inventoryData) throws DataDeserializationException {
public static CompletableFuture<BukkitInventoryMap> deserializeInventory(@NotNull String serializedPlayerInventory)
throws DataDeserializationException {
return CompletableFuture.supplyAsync(() -> new BukkitInventoryMap(deserializeItemStackArray(serializedPlayerInventory).join()));
}
/**
* Returns an array of ItemStacks from serialized inventory data.
*
* @param serializeItemStackArray The serialized {@link ItemStack[]} array
* @return The deserialized array of {@link ItemStack}s
* @throws DataDeserializationException If the serialized item stack array could not be deserialized
* @implNote Empty slots will be represented by {@code null}
*/
public static CompletableFuture<ItemStack[]> deserializeItemStackArray(String serializeItemStackArray)
throws DataDeserializationException {
return CompletableFuture.supplyAsync(() -> {
// Return empty array if there is no inventory data (set the player as having an empty inventory)
if (inventoryData.isEmpty()) {
if (serializeItemStackArray.isEmpty()) {
return new ItemStack[0];
}
// Create a byte input stream to read the serialized data
try (ByteArrayInputStream byteInputStream = new ByteArrayInputStream(Base64Coder.decodeLines(inventoryData))) {
try (ByteArrayInputStream byteInputStream = new ByteArrayInputStream(Base64Coder.decodeLines(serializeItemStackArray))) {
try (BukkitObjectInputStream bukkitInputStream = new BukkitObjectInputStream(byteInputStream)) {
// Read the length of the Bukkit input stream and set the length of the array to this value
ItemStack[] inventoryContents = new ItemStack[bukkitInputStream.readInt()];

View File

@@ -0,0 +1,60 @@
package net.william278.husksync.event;
import net.william278.husksync.data.DataSaveCause;
import net.william278.husksync.data.UserData;
import net.william278.husksync.player.User;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitDataSavePlayerEvent extends BukkitEvent implements DataSaveEvent, Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
private boolean cancelled = false;
private UserData userData;
private final User user;
private final DataSaveCause saveCause;
protected BukkitDataSavePlayerEvent(@NotNull User user, @NotNull UserData userData,
@NotNull DataSaveCause saveCause) {
this.user = user;
this.userData = userData;
this.saveCause = saveCause;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@NotNull
@Override
public User getUser() {
return user;
}
@Override
public @NotNull UserData getUserData() {
return userData;
}
@Override
public void setUserData(@NotNull UserData userData) {
this.userData = userData;
}
@Override
public @NotNull DataSaveCause getSaveCause() {
return saveCause;
}
@NotNull
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
}

View File

@@ -0,0 +1,25 @@
package net.william278.husksync.event;
import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.player.BukkitPlayer;
import net.william278.husksync.player.OnlineUser;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
public abstract class BukkitEvent extends Event implements net.william278.husksync.event.Event {
@Override
public CompletableFuture<net.william278.husksync.event.Event> fire() {
final CompletableFuture<net.william278.husksync.event.Event> eventFireFuture = new CompletableFuture<>();
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
Bukkit.getServer().getPluginManager().callEvent(this);
eventFireFuture.complete(this);
});
return eventFireFuture;
}
}

View File

@@ -0,0 +1,33 @@
package net.william278.husksync.event;
import net.william278.husksync.data.DataSaveCause;
import net.william278.husksync.data.UserData;
import net.william278.husksync.player.BukkitPlayer;
import net.william278.husksync.player.OnlineUser;
import net.william278.husksync.player.User;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
public class BukkitEventCannon extends EventCannon {
public BukkitEventCannon() {
}
@Override
public CompletableFuture<Event> firePreSyncEvent(@NotNull OnlineUser user, @NotNull UserData userData) {
return new BukkitPreSyncEvent(((BukkitPlayer) user).getPlayer(), userData).fire();
}
@Override
public CompletableFuture<Event> fireDataSaveEvent(@NotNull User user, @NotNull UserData userData,
@NotNull DataSaveCause saveCause) {
return new BukkitDataSavePlayerEvent(user, userData, saveCause).fire();
}
@Override
public void fireSyncCompleteEvent(@NotNull OnlineUser user) {
new BukkitSyncCompletePlayerEvent(((BukkitPlayer) user).getPlayer()).fire();
}
}

View File

@@ -0,0 +1,34 @@
package net.william278.husksync.event;
import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.player.BukkitPlayer;
import net.william278.husksync.player.OnlineUser;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
public abstract class BukkitPlayerEvent extends org.bukkit.event.player.PlayerEvent implements PlayerEvent {
public BukkitPlayerEvent(@NotNull Player who) {
super(who);
}
@Override
public OnlineUser getUser() {
return BukkitPlayer.adapt(player);
}
@Override
public CompletableFuture<Event> fire() {
final CompletableFuture<Event> eventFireFuture = new CompletableFuture<>();
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
Bukkit.getServer().getPluginManager().callEvent(this);
eventFireFuture.complete(this);
});
return eventFireFuture;
}
}

View File

@@ -0,0 +1,51 @@
package net.william278.husksync.event;
import net.william278.husksync.data.UserData;
import net.william278.husksync.player.BukkitPlayer;
import net.william278.husksync.player.OnlineUser;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitPreSyncEvent extends BukkitPlayerEvent implements PreSyncEvent, Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
private boolean cancelled = false;
private UserData userData;
protected BukkitPreSyncEvent(@NotNull Player player, @NotNull UserData userData) {
super(player);
this.userData = userData;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@Override
public OnlineUser getUser() {
return BukkitPlayer.adapt(player);
}
@Override
public @NotNull UserData getUserData() {
return userData;
}
@Override
public void setUserData(@NotNull UserData userData) {
this.userData = userData;
}
@NotNull
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
}

View File

@@ -0,0 +1,26 @@
package net.william278.husksync.event;
import net.william278.husksync.player.BukkitPlayer;
import net.william278.husksync.player.OnlineUser;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BukkitSyncCompletePlayerEvent extends BukkitPlayerEvent implements SyncCompleteEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
protected BukkitSyncCompletePlayerEvent(@NotNull Player player) {
super(player);
}
@Override
public OnlineUser getUser() {
return BukkitPlayer.adapt(player);
}
@NotNull
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
}

View File

@@ -3,7 +3,7 @@ package net.william278.husksync.listener;
import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.data.BukkitSerializer;
import net.william278.husksync.data.DataDeserializationException;
import net.william278.husksync.data.InventoryData;
import net.william278.husksync.data.ItemData;
import net.william278.husksync.player.BukkitPlayer;
import net.william278.husksync.player.OnlineUser;
import org.bukkit.Bukkit;
@@ -41,7 +41,6 @@ public class BukkitEventListener extends EventListener implements Listener {
@EventHandler
public void onPlayerQuit(@NotNull PlayerQuitEvent event) {
super.handlePlayerQuit(BukkitPlayer.adapt(event.getPlayer()));
BukkitPlayer.remove(event.getPlayer());
}
@EventHandler(ignoreCancelled = true)
@@ -56,8 +55,8 @@ public class BukkitEventListener extends EventListener implements Listener {
final OnlineUser user = BukkitPlayer.adapt(player);
if (huskSync.getDataEditor().isEditingInventoryData(user)) {
try {
BukkitSerializer.serializeInventory(event.getInventory().getContents()).thenAccept(
serializedInventory -> super.handleMenuClose(user, new InventoryData(serializedInventory)));
BukkitSerializer.serializeItemStackArray(event.getInventory().getContents()).thenAccept(
serializedInventory -> super.handleMenuClose(user, new ItemData(serializedInventory)));
} catch (DataDeserializationException e) {
huskSync.getLoggingAdapter().log(Level.SEVERE,
"Failed to serialize inventory data during menu close", e);

View File

@@ -31,7 +31,6 @@ import java.util.concurrent.atomic.AtomicReference;
*/
public class BukkitPlayer extends OnlineUser {
private static final HashMap<UUID, BukkitPlayer> cachedPlayers = new HashMap<>();
private final Player player;
private BukkitPlayer(@NotNull Player player) {
@@ -40,16 +39,11 @@ public class BukkitPlayer extends OnlineUser {
}
public static BukkitPlayer adapt(@NotNull Player player) {
if (cachedPlayers.containsKey(player.getUniqueId())) {
return cachedPlayers.get(player.getUniqueId());
}
final BukkitPlayer bukkitPlayer = new BukkitPlayer(player);
cachedPlayers.put(player.getUniqueId(), bukkitPlayer);
return bukkitPlayer;
return new BukkitPlayer(player);
}
public static void remove(@NotNull Player player) {
cachedPlayers.remove(player.getUniqueId());
public Player getPlayer() {
return player;
}
@Override
@@ -73,21 +67,18 @@ public class BukkitPlayer extends OnlineUser {
@Override
public CompletableFuture<Void> setStatus(@NotNull StatusData statusData,
final boolean setHealth, final boolean setMaxHealth,
final boolean setHunger, final boolean setExperience,
final boolean setGameMode, final boolean setFlying,
final boolean setSelectedItemSlot) {
@NotNull List<StatusDataFlag> statusDataFlags) {
return CompletableFuture.runAsync(() -> {
double currentMaxHealth = Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH))
.getBaseValue();
if (setMaxHealth) {
if (statusDataFlags.contains(StatusDataFlag.SET_MAX_HEALTH)) {
if (statusData.maxHealth != 0d) {
Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH))
.setBaseValue(statusData.maxHealth);
currentMaxHealth = statusData.maxHealth;
}
}
if (setHealth) {
if (statusDataFlags.contains(StatusDataFlag.SET_HEALTH)) {
final double currentHealth = player.getHealth();
if (statusData.health != currentHealth) {
player.setHealth(currentHealth > currentMaxHealth ? currentMaxHealth : statusData.health);
@@ -100,24 +91,24 @@ public class BukkitPlayer extends OnlineUser {
}
player.setHealthScaled(statusData.healthScale != 0D);
}
if (setHunger) {
if (statusDataFlags.contains(StatusDataFlag.SET_HUNGER)) {
player.setFoodLevel(statusData.hunger);
player.setSaturation(statusData.saturation);
player.setExhaustion(statusData.saturationExhaustion);
}
if (setSelectedItemSlot) {
if (statusDataFlags.contains(StatusDataFlag.SET_SELECTED_ITEM_SLOT)) {
player.getInventory().setHeldItemSlot(statusData.selectedItemSlot);
}
if (setExperience) {
if (statusDataFlags.contains(StatusDataFlag.SET_EXPERIENCE)) {
player.setTotalExperience(statusData.totalExperience);
player.setLevel(statusData.expLevel);
player.setExp(statusData.expProgress);
}
if (setGameMode) {
if (statusDataFlags.contains(StatusDataFlag.SET_GAME_MODE)) {
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () ->
player.setGameMode(GameMode.valueOf(statusData.gameMode)));
}
if (setFlying) {
if (statusDataFlags.contains(StatusDataFlag.SET_FLYING)) {
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
if (statusData.isFlying) {
player.setAllowFlight(true);
@@ -130,29 +121,39 @@ public class BukkitPlayer extends OnlineUser {
}
@Override
public CompletableFuture<InventoryData> getInventory() {
return BukkitSerializer.serializeInventory(player.getInventory().getContents())
.thenApply(InventoryData::new);
public CompletableFuture<ItemData> getInventory() {
return BukkitSerializer.serializeItemStackArray(player.getInventory().getContents())
.thenApply(ItemData::new);
}
@Override
public CompletableFuture<Void> setInventory(@NotNull InventoryData inventoryData) {
return BukkitSerializer.deserializeInventory(inventoryData.serializedInventory).thenAccept(contents ->
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
() -> player.getInventory().setContents(contents)));
public CompletableFuture<Void> setInventory(@NotNull ItemData itemData) {
return BukkitSerializer.deserializeInventory(itemData.serializedItems).thenApplyAsync(contents -> {
final CompletableFuture<Void> inventorySetFuture = new CompletableFuture<>();
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
player.getInventory().setContents(contents.getContents());
inventorySetFuture.complete(null);
});
return inventorySetFuture.join();
});
}
@Override
public CompletableFuture<InventoryData> getEnderChest() {
return BukkitSerializer.serializeInventory(player.getEnderChest().getContents())
.thenApply(InventoryData::new);
public CompletableFuture<ItemData> getEnderChest() {
return BukkitSerializer.serializeItemStackArray(player.getEnderChest().getContents())
.thenApply(ItemData::new);
}
@Override
public CompletableFuture<Void> setEnderChest(@NotNull InventoryData enderChestData) {
return BukkitSerializer.deserializeInventory(enderChestData.serializedInventory).thenAccept(contents ->
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(),
() -> player.getEnderChest().setContents(contents)));
public CompletableFuture<Void> setEnderChest(@NotNull ItemData enderChestData) {
return BukkitSerializer.deserializeItemStackArray(enderChestData.serializedItems).thenApplyAsync(contents -> {
final CompletableFuture<Void> enderChestSetFuture = new CompletableFuture<>();
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
player.getEnderChest().setContents(contents);
enderChestSetFuture.complete(null);
});
return enderChestSetFuture.join();
});
}
@Override
@@ -163,15 +164,20 @@ public class BukkitPlayer extends OnlineUser {
@Override
public CompletableFuture<Void> setPotionEffects(@NotNull PotionEffectData potionEffectData) {
return BukkitSerializer.deserializePotionEffects(potionEffectData.serializedPotionEffects).thenAccept(
effects -> Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
for (PotionEffect effect : player.getActivePotionEffects()) {
player.removePotionEffect(effect.getType());
}
for (PotionEffect effect : effects) {
player.addPotionEffect(effect);
}
}));
return BukkitSerializer.deserializePotionEffects(potionEffectData.serializedPotionEffects)
.thenApplyAsync(effects -> {
final CompletableFuture<Void> potionEffectsSetFuture = new CompletableFuture<>();
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
for (PotionEffect effect : player.getActivePotionEffects()) {
player.removePotionEffect(effect.getType());
}
for (PotionEffect effect : effects) {
player.addPotionEffect(effect);
}
potionEffectsSetFuture.complete(null);
});
return potionEffectsSetFuture.join();
});
}
@Override
@@ -362,7 +368,7 @@ public class BukkitPlayer extends OnlineUser {
@Override
public CompletableFuture<Void> setLocation(@NotNull LocationData locationData) {
final CompletableFuture<Void> completableFuture = new CompletableFuture<>();
final CompletableFuture<Void> teleportFuture = new CompletableFuture<>();
AtomicReference<World> bukkitWorld = new AtomicReference<>(Bukkit.getWorld(locationData.worldName));
if (bukkitWorld.get() == null) {
bukkitWorld.set(Bukkit.getWorld(locationData.worldUuid));
@@ -372,12 +378,14 @@ public class BukkitPlayer extends OnlineUser {
.valueOf(locationData.worldEnvironment)).findFirst().ifPresent(bukkitWorld::set);
}
if (bukkitWorld.get() != null) {
player.teleport(new Location(bukkitWorld.get(),
locationData.x, locationData.y, locationData.z,
locationData.yaw, locationData.pitch), PlayerTeleportEvent.TeleportCause.PLUGIN);
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
player.teleport(new Location(bukkitWorld.get(),
locationData.x, locationData.y, locationData.z,
locationData.yaw, locationData.pitch), PlayerTeleportEvent.TeleportCause.PLUGIN);
teleportFuture.complete(null);
});
}
CompletableFuture.runAsync(() -> completableFuture.completeAsync(() -> null));
return completableFuture;
return teleportFuture;
}
@Override
@@ -413,12 +421,17 @@ public class BukkitPlayer extends OnlineUser {
@Override
public boolean isDead() {
return player.isDead() || player.getHealth() <= 0;
return player.getHealth() <= 0d;
}
@Override
public boolean isOffline() {
return player == null;
try {
return player == null;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Override
@@ -428,7 +441,7 @@ public class BukkitPlayer extends OnlineUser {
@Override
public void showMenu(@NotNull InventoryEditorMenu menu) {
BukkitSerializer.deserializeInventory(menu.inventoryData.serializedInventory).thenAccept(inventoryContents -> {
BukkitSerializer.deserializeItemStackArray(menu.itemData.serializedItems).thenAccept(inventoryContents -> {
final Inventory inventory = Bukkit.createInventory(player, menu.slotCount,
BaseComponent.toLegacyText(menu.menuTitle.toComponent()));
inventory.setContents(inventoryContents);

View File

@@ -1,37 +1,39 @@
package net.william278.husksync.util;
import org.jetbrains.annotations.NotNull;
import java.util.logging.Level;
public class BukkitLogger implements Logger {
public class BukkitLogger extends Logger {
private final java.util.logging.Logger logger;
public BukkitLogger(java.util.logging.Logger logger) {
public BukkitLogger(@NotNull java.util.logging.Logger logger) {
this.logger = logger;
}
@Override
public void log(Level level, String message, Exception e) {
public void log(@NotNull Level level, @NotNull String message, @NotNull Exception e) {
logger.log(level, message, e);
}
@Override
public void log(Level level, String message) {
public void log(@NotNull Level level, @NotNull String message) {
logger.log(level, message);
}
@Override
public void info(String message) {
public void info(@NotNull String message) {
logger.info(message);
}
@Override
public void severe(String message) {
public void severe(@NotNull String message) {
logger.severe(message);
}
@Override
public void config(String message) {
public void config(@NotNull String message) {
logger.config(message);
}