Furnace ownership tweaks

This commit is contained in:
nossr50 2020-07-28 21:56:51 -07:00
parent 274a41f530
commit 38122d8f17
17 changed files with 234 additions and 108 deletions

View File

@ -1,5 +1,6 @@
Version 2.1.136
Furnace ownership was made more reliable
Furnace ownership is no longer lost when the furnace stops doing a job
Furnaces remember owners between restarts (requires MC 1.14 or higher)
Version 2.1.135
Furnaces no longer simulate block break checks when assigning ownership as it caused some unwanted plugin conflicts

View File

@ -0,0 +1,20 @@
package com.gmail.nossr50.datatypes.meta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class UUIDMeta extends FixedMetadataValue {
/**
* Initializes a FixedMetadataValue with an Object
*
* @param owningPlugin the {@link Plugin} that created this metadata value
* @param value the value assigned to this metadata value
*/
public UUIDMeta(@NotNull Plugin owningPlugin, @Nullable UUID value) {
super(owningPlugin, value);
}
}

View File

@ -18,7 +18,6 @@ import com.gmail.nossr50.skills.herbalism.HerbalismManager;
import com.gmail.nossr50.skills.mining.MiningManager;
import com.gmail.nossr50.skills.repair.Repair;
import com.gmail.nossr50.skills.salvage.Salvage;
import com.gmail.nossr50.skills.smelting.Smelting;
import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.EventUtils;
@ -39,10 +38,8 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue;
import java.util.HashSet;
import java.util.List;
public class BlockListener implements Listener {
private final mcMMO plugin;
@ -666,7 +663,7 @@ public class BlockListener implements Listener {
if(mcMMO.getSmeltingTracker().isFurnaceOwned(furnace))
{
player.sendMessage("[mcMMO DEBUG] This furnace has a registered owner");
OfflinePlayer furnacePlayer = mcMMO.getSmeltingTracker().getPlayerFromFurnace(furnace);
OfflinePlayer furnacePlayer = mcMMO.getSmeltingTracker().getFurnaceOwner(furnace);
if(furnacePlayer != null)
{
player.sendMessage("[mcMMO DEBUG] This furnace is owned by player "+furnacePlayer.getName());

View File

@ -8,7 +8,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.events.fake.FakeBrewEvent;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.player.PlayerUpdateInventoryTask;
import com.gmail.nossr50.runnables.skills.FurnaceCleanupTask;
import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.alchemy.AlchemyPotionBrewer;
import com.gmail.nossr50.util.ItemUtils;
@ -56,7 +55,7 @@ public class InventoryListener implements Listener {
Furnace furnace = (Furnace) furnaceState;
OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getPlayerFromFurnace(furnace);
OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getFurnaceOwner(furnace);
if(offlinePlayer != null && offlinePlayer.isOnline()) {
@ -94,7 +93,7 @@ public class InventoryListener implements Listener {
if(blockState instanceof Furnace) {
Furnace furnace = (Furnace) blockState;
OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getPlayerFromFurnace(furnace);
OfflinePlayer offlinePlayer = mcMMO.getSmeltingTracker().getFurnaceOwner(furnace);
if(offlinePlayer != null) {
@ -105,8 +104,6 @@ public class InventoryListener implements Listener {
event.setResult(offlineProfile.getSmeltingManager().smeltProcessing(smelting, event.getResult()));
}
}
new FurnaceCleanupTask(furnace).runTaskLater(mcMMO.p, 1);
}
}

View File

@ -1,23 +0,0 @@
package com.gmail.nossr50.runnables.skills;
import com.gmail.nossr50.mcMMO;
import org.bukkit.block.Furnace;
import org.bukkit.scheduler.BukkitRunnable;
public class FurnaceCleanupTask extends BukkitRunnable {
private final Furnace furnace;
public FurnaceCleanupTask(Furnace furnace) {
this.furnace = furnace;
}
@Override
public void run() {
if(furnace != null
&& furnace.getInventory().getSmelting() == null) {
//Furnace is empty so stop tracking it
mcMMO.getSmeltingTracker().untrackFurnace(furnace);
}
}
}

View File

@ -2,24 +2,8 @@ package com.gmail.nossr50.skills.smelting;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Furnace;
import org.bukkit.entity.Player;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
public class Smelting {

View File

@ -3,7 +3,10 @@ package com.gmail.nossr50.util.compat;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.compat.layers.PlayerAttackCooldownExploitPreventionLayer;
import com.gmail.nossr50.util.compat.layers.attackcooldown.PlayerAttackCooldownExploitPreventionLayer;
import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer;
import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataLayer;
import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotTemporaryDataLayer;
import com.gmail.nossr50.util.nms.NMSVersion;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import org.bukkit.command.CommandSender;
@ -24,6 +27,7 @@ public class CompatibilityManager {
/* Compatibility Layers */
private PlayerAttackCooldownExploitPreventionLayer playerAttackCooldownExploitPreventionLayer;
private AbstractPersistentDataLayer persistentDataLayer;
public CompatibilityManager(MinecraftGameVersion minecraftGameVersion) {
mcMMO.p.getLogger().info("Loading compatibility layers...");
@ -42,6 +46,10 @@ public class CompatibilityManager {
supportedLayers = new HashMap<>(); //Init map
for(CompatibilityType compatibilityType : CompatibilityType.values()) {
//TODO: Remove later
if(compatibilityType == CompatibilityType.PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION)
continue;
supportedLayers.put(compatibilityType, false); //All layers are set to false when initialized
}
}
@ -51,26 +59,21 @@ public class CompatibilityManager {
* For any unsupported layers, load a dummy layer
*/
private void initCompatibilityLayers() {
isFullyCompatibleServerSoftware = true;
initPersistentDataLayer();
// if(nmsVersion == NMSVersion.UNSUPPORTED) {
// mcMMO.p.getLogger().info("NMS not supported for this version of Minecraft, possible solutions include updating mcMMO or updating your server software. NMS Support is not available on every version of Minecraft.");
// mcMMO.p.getLogger().info("Certain features of mcMMO that require NMS will be disabled, you can check what is disabled by running the /mmocompat command!");
// //Load dummy compatibility layers
// isFullyCompatibleServerSoftware = false;
// loadDummyCompatibilityLayers();
// } else {
// playerAttackCooldownExploitPreventionLayer = new PlayerAttackCooldownExploitPreventionLayer(nmsVersion);
//
// //Mark as operational
// if(playerAttackCooldownExploitPreventionLayer.noErrorsOnInitialize()) {
// supportedLayers.put(CompatibilityType.PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION, true);
// }
// }
isFullyCompatibleServerSoftware = true;
}
private void loadDummyCompatibilityLayers() {
private void initPersistentDataLayer() {
if(minecraftGameVersion.getMinorVersion().asInt() >= 14 || minecraftGameVersion.getMajorVersion().asInt() >= 2) {
persistentDataLayer = new SpigotPersistentDataLayer();
} else {
persistentDataLayer = new SpigotTemporaryDataLayer();
}
supportedLayers.put(CompatibilityType.PERSISTENT_DATA, true);
}
//TODO: move to text manager
@ -128,4 +131,7 @@ public class CompatibilityManager {
return playerAttackCooldownExploitPreventionLayer;
}
public AbstractPersistentDataLayer getPersistentDataLayer() {
return persistentDataLayer;
}
}

View File

@ -1,5 +1,6 @@
package com.gmail.nossr50.util.compat;
public enum CompatibilityType {
PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION
PLAYER_ATTACK_COOLDOWN_EXPLOIT_PREVENTION,
PERSISTENT_DATA
}

View File

@ -1,8 +1,6 @@
package com.gmail.nossr50.util.compat.layers;
import com.gmail.nossr50.util.compat.CompatibilityLayer;
import com.gmail.nossr50.util.nms.NMSVersion;
import org.jetbrains.annotations.NotNull;
/**
*
@ -13,11 +11,6 @@ import org.jetbrains.annotations.NotNull;
public abstract class AbstractCompatibilityLayer implements CompatibilityLayer {
protected boolean noErrorsOnInitialize = true;
protected final @NotNull NMSVersion nmsVersion;
public AbstractCompatibilityLayer(@NotNull NMSVersion nmsVersion) {
this.nmsVersion = nmsVersion;
}
/**
* Initialize the CompatibilityLayer

View File

@ -0,0 +1,30 @@
package com.gmail.nossr50.util.compat.layers;
import com.gmail.nossr50.util.nms.NMSVersion;
import org.jetbrains.annotations.NotNull;
/**
*
* These classes are a band-aid solution for adding NMS support into 2.1.XXX
* In 2.2 we are switching to modules and that will clean things up significantly
*
*/
public abstract class AbstractNMSCompatibilityLayer extends AbstractCompatibilityLayer {
protected final @NotNull NMSVersion nmsVersion;
public AbstractNMSCompatibilityLayer(@NotNull NMSVersion nmsVersion) {
this.nmsVersion = nmsVersion;
}
/**
* Initialize the CompatibilityLayer
* @return true if the CompatibilityLayer initialized and should be functional
*/
public abstract boolean initializeLayer();
@Override
public boolean noErrorsOnInitialize() {
return noErrorsOnInitialize;
}
}

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.util.compat.layers;
package com.gmail.nossr50.util.compat.layers.attackcooldown;
import com.gmail.nossr50.util.nms.NMSVersion;
import org.bukkit.entity.Player;

View File

@ -1,6 +1,7 @@
package com.gmail.nossr50.util.compat.layers;
package com.gmail.nossr50.util.compat.layers.attackcooldown;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.layers.AbstractNMSCompatibilityLayer;
import com.gmail.nossr50.util.nms.NMSConstants;
import com.gmail.nossr50.util.nms.NMSVersion;
import org.bukkit.entity.Player;
@ -16,7 +17,7 @@ import java.lang.reflect.Method;
* In 2.2 we are switching to modules and that will clean things up significantly
*
*/
public class PlayerAttackCooldownExploitPreventionLayer extends AbstractCompatibilityLayer implements PlayerAttackCooldownMethods{
public class PlayerAttackCooldownExploitPreventionLayer extends AbstractNMSCompatibilityLayer implements PlayerAttackCooldownMethods{
private final String cbNMSVersionPath;

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.util.compat.layers;
package com.gmail.nossr50.util.compat.layers.attackcooldown;
import org.bukkit.entity.Player;

View File

@ -0,0 +1,19 @@
package com.gmail.nossr50.util.compat.layers.persistentdata;
import com.gmail.nossr50.util.compat.layers.AbstractCompatibilityLayer;
import org.bukkit.block.Furnace;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public abstract class AbstractPersistentDataLayer extends AbstractCompatibilityLayer {
public AbstractPersistentDataLayer() {
initializeLayer();
}
public abstract @Nullable UUID getFurnaceOwner(Furnace furnace);
public abstract void setFurnaceOwner(Furnace furnace, UUID uuid);
}

View File

@ -0,0 +1,60 @@
package com.gmail.nossr50.util.compat.layers.persistentdata;
import com.gmail.nossr50.mcMMO;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Furnace;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataHolder;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class SpigotPersistentDataLayer extends AbstractPersistentDataLayer {
private NamespacedKey furnaceOwner_MostSig_Key;
private NamespacedKey furnaceOwner_LeastSig_Key;
@Override
public boolean initializeLayer() {
initNamespacedKeys();
return true;
}
private void initNamespacedKeys() {
furnaceOwner_MostSig_Key = getNamespacedKey("furnace_uuid_most_sig");
furnaceOwner_LeastSig_Key = getNamespacedKey("furnace_uuid_least_sig");
}
@NotNull
public NamespacedKey getNamespacedKey(String key) {
return new NamespacedKey(mcMMO.p, key);
}
@Override
public @Nullable UUID getFurnaceOwner(Furnace furnace) {
//Get container from entity
PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer();
Long mostSigBits = dataContainer.get(furnaceOwner_MostSig_Key, PersistentDataType.LONG);
Long leastSigBits = dataContainer.get(furnaceOwner_LeastSig_Key, PersistentDataType.LONG);
if(mostSigBits != null && leastSigBits != null) {
return new UUID(mostSigBits, leastSigBits);
} else {
return null;
}
}
@Override
public void setFurnaceOwner(Furnace furnace, UUID uuid) {
PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer();
dataContainer.set(furnaceOwner_MostSig_Key, PersistentDataType.LONG, uuid.getMostSignificantBits());
dataContainer.set(furnaceOwner_LeastSig_Key, PersistentDataType.LONG, uuid.getLeastSignificantBits());
furnace.update();
}
}

View File

@ -0,0 +1,44 @@
package com.gmail.nossr50.util.compat.layers.persistentdata;
import com.gmail.nossr50.datatypes.meta.UUIDMeta;
import com.gmail.nossr50.mcMMO;
import org.bukkit.block.Furnace;
import org.bukkit.metadata.Metadatable;
import java.util.UUID;
/**
* Persistent Data API is unavailable
*/
public class SpigotTemporaryDataLayer extends AbstractPersistentDataLayer {
private final String FURNACE_OWNER_METADATA_KEY = "mcMMO_furnace_owner";
@Override
public boolean initializeLayer() {
return true;
}
@Override
public UUID getFurnaceOwner(Furnace furnace) {
Metadatable metadatable = (Metadatable) furnace;
if(metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).size() > 0) {
UUIDMeta uuidMeta = (UUIDMeta) metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).get(0);
return (UUID) uuidMeta.value();
} else {
return null;
}
}
@Override
public void setFurnaceOwner(Furnace furnace, UUID uuid) {
Metadatable metadatable = (Metadatable) furnace;
if(metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).size() > 0) {
metadatable.removeMetadata(FURNACE_OWNER_METADATA_KEY, mcMMO.p);
}
metadatable.setMetadata(FURNACE_OWNER_METADATA_KEY, new UUIDMeta(mcMMO.p, uuid));
}
}

View File

@ -3,8 +3,6 @@ package com.gmail.nossr50.util.skills;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.smelting.Smelting;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.Bukkit;
@ -16,15 +14,11 @@ import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.UUID;
public class SmeltingTracker {
private final HashMap<Furnace, OfflinePlayer> furnaceOwners;
public SmeltingTracker() {
furnaceOwners = new HashMap<>();
}
// private final HashMap<Furnace, OfflinePlayer> furnaceOwners;
private void changeFurnaceOwnership(Furnace furnace, Player player) {
@ -37,7 +31,11 @@ public class SmeltingTracker {
printOwnershipLossDebug(furnace);
furnaceOwners.put(furnace, player);
setFurnaceOwner(furnace, player);
}
private void setFurnaceOwner(Furnace furnace, Player player) {
mcMMO.getCompatibilityManager().getPersistentDataLayer().setFurnaceOwner(furnace, player.getUniqueId());
}
private void printOwnershipGainDebug(Furnace furnace, McMMOPlayer mcMMOPlayer) {
@ -52,23 +50,31 @@ public class SmeltingTracker {
}
private void printOwnershipLossDebug(Furnace furnace) {
if(furnaceOwners.get(furnace) != null) {
OfflinePlayer furnaceOwner = furnaceOwners.get(furnace);
OfflinePlayer furnaceOwner = getFurnaceOwner(furnace);
if(furnaceOwner.isOnline()) {
McMMOPlayer furnaceOwnerProfile = UserManager.getPlayer(furnaceOwner.getPlayer());
if(furnaceOwner != null && furnaceOwner.isOnline()) {
McMMOPlayer furnaceOwnerProfile = UserManager.getPlayer(furnaceOwner.getPlayer());
if(furnaceOwnerProfile != null) {
if(furnaceOwnerProfile.isDebugMode()) {
furnaceOwnerProfile.getPlayer().sendMessage("Furnace ownership " +
ChatColor.RED + "lost " + ChatColor.RESET +
"at location: " + furnace.getLocation().toString());
}
if(furnaceOwnerProfile != null) {
if(furnaceOwnerProfile.isDebugMode()) {
furnaceOwnerProfile.getPlayer().sendMessage("Furnace ownership " +
ChatColor.RED + "lost " + ChatColor.RESET +
"at location: " + furnace.getLocation().toString());
}
}
}
}
public @Nullable OfflinePlayer getFurnaceOwner(Furnace furnace) {
UUID uuid = mcMMO.getCompatibilityManager().getPersistentDataLayer().getFurnaceOwner(furnace);
if(uuid != null) {
return Bukkit.getOfflinePlayer(uuid);
} else {
return null;
}
}
@Nullable
public Furnace getFurnaceFromInventory(Inventory inventory) {
if (!(inventory instanceof FurnaceInventory)) {
@ -78,13 +84,8 @@ public class SmeltingTracker {
return (Furnace) inventory.getHolder();
}
@Nullable
public OfflinePlayer getPlayerFromFurnace(Furnace furnace) {
return furnaceOwners.get(furnace);
}
public boolean isFurnaceOwned(Furnace furnace) {
return furnaceOwners.get(furnace) != null;
return getFurnaceOwner(furnace) != null;
}
public void processFurnaceOwnership(Furnace furnace, Player player) {
@ -93,9 +94,4 @@ public class SmeltingTracker {
changeFurnaceOwnership(furnace, player);
}
public void untrackFurnace(Furnace furnace) {
printOwnershipLossDebug(furnace);
furnaceOwners.remove(furnace);
}
}