Save & restore all attributes

This commit is contained in:
Daniel Saukel 2020-10-28 18:46:55 +01:00
parent d3662918c2
commit 4421bdd579
4 changed files with 162 additions and 28 deletions

View File

@ -42,6 +42,8 @@ import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
@ -474,23 +476,30 @@ public class DGlobalPlayer implements GlobalPlayer {
} }
player.setLevel(data.getOldLevel()); player.setLevel(data.getOldLevel());
player.setExp(data.getOldExp()); player.setExp(data.getOldExp());
if (is1_9) {
player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(data.getOldMaxHealth());
player.setHealth(data.getOldHealth() <= data.getOldMaxHealth() ? data.getOldHealth() : data.getOldMaxHealth());
} else {
player.setHealth(player.getMaxHealth());
}
player.setFoodLevel(data.getOldFoodLevel()); player.setFoodLevel(data.getOldFoodLevel());
player.setFireTicks(data.getOldFireTicks()); player.setFireTicks(data.getOldFireTicks());
for (PotionEffect effect : player.getActivePotionEffects()) { for (PotionEffect effect : player.getActivePotionEffects()) {
player.removePotionEffect(effect.getType()); player.removePotionEffect(effect.getType());
} }
player.addPotionEffects(data.getOldPotionEffects()); player.addPotionEffects(data.getOldPotionEffects());
if (is1_9) { if (is1_9) {
player.setCollidable(data.getOldCollidabilityState()); player.setCollidable(data.getOldCollidabilityState());
player.setInvulnerable(data.getOldInvulnerabilityState()); player.setInvulnerable(data.getOldInvulnerabilityState());
for (Attribute attribute : Attribute.values()) {
AttributeInstance instance = player.getAttribute(attribute);
if (instance == null) {
continue;
}
instance.setBaseValue((double) data.getOldAttributeBases().get(attribute));
for (AttributeModifier mod : instance.getModifiers()) {
instance.removeModifier(mod);
}
for (/*AttributeModifier*/Object mod : data.getOldAttributeMods().get(attribute)) { // TODO Remove casts when 1.8 is dropped
instance.addModifier((AttributeModifier) mod);
}
}
} }
player.setAllowFlight(data.getOldFlyingState()); player.setAllowFlight(data.getOldFlyingState());

View File

@ -22,6 +22,7 @@ import de.erethon.dungeonsxl.api.player.InstancePlayer;
import de.erethon.dungeonsxl.api.world.GameWorld; import de.erethon.dungeonsxl.api.world.GameWorld;
import de.erethon.dungeonsxl.api.world.InstanceWorld; import de.erethon.dungeonsxl.api.world.InstanceWorld;
import de.erethon.dungeonsxl.config.MainConfig; import de.erethon.dungeonsxl.config.MainConfig;
import de.erethon.dungeonsxl.util.AttributeUtil;
import de.erethon.dungeonsxl.util.ParsingUtil; import de.erethon.dungeonsxl.util.ParsingUtil;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
@ -80,6 +81,7 @@ public abstract class DInstancePlayer extends DGlobalPlayer implements InstanceP
player.setLevel(0); player.setLevel(0);
double maxHealth; double maxHealth;
if (is1_9) { if (is1_9) {
AttributeUtil.resetPlayerAttributes(player);
maxHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(); maxHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
} else { } else {
maxHealth = player.getMaxHealth(); maxHealth = player.getMaxHealth();

View File

@ -16,8 +16,11 @@
*/ */
package de.erethon.dungeonsxl.player; package de.erethon.dungeonsxl.player;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import de.erethon.commons.chat.MessageUtil; import de.erethon.commons.chat.MessageUtil;
import de.erethon.commons.compatibility.Internals; import de.erethon.commons.compatibility.Internals;
import de.erethon.commons.config.ConfigUtil;
import de.erethon.commons.config.DREConfig; import de.erethon.commons.config.DREConfig;
import de.erethon.commons.javaplugin.DREPlugin; import de.erethon.commons.javaplugin.DREPlugin;
import de.erethon.commons.misc.EnumUtil; import de.erethon.commons.misc.EnumUtil;
@ -29,10 +32,13 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
@ -59,12 +65,13 @@ public class DPlayerData extends DREConfig {
private ItemStack oldOffHand; private ItemStack oldOffHand;
private int oldLvl; private int oldLvl;
private float oldExp; private float oldExp;
private double oldMaxHealth;
private double oldHealth; private double oldHealth;
private int oldFoodLevel; private int oldFoodLevel;
private int oldFireTicks; private int oldFireTicks;
private GameMode oldGameMode; private GameMode oldGameMode;
private Collection<PotionEffect> oldPotionEffects; private Collection<PotionEffect> oldPotionEffects;
private Map/*<Attribute, Double>*/ oldAttributeBases;
private Multimap/*<Attribute, AttributeModifier>*/ oldAttributeMods;
private boolean oldCollidabilityState; private boolean oldCollidabilityState;
private boolean oldFlyingState; private boolean oldFlyingState;
private boolean oldInvulnerabilityState; private boolean oldInvulnerabilityState;
@ -195,20 +202,6 @@ public class DPlayerData extends DREConfig {
oldExp = exp; oldExp = exp;
} }
/**
* @return the old max health
*/
public double getOldMaxHealth() {
return oldMaxHealth;
}
/**
* @param maxHealth the maximum health to set
*/
public void setOldMaxHealth(double maxHealth) {
oldMaxHealth = maxHealth;
}
/** /**
* @return the old health * @return the old health
*/ */
@ -279,6 +272,34 @@ public class DPlayerData extends DREConfig {
oldPotionEffects = potionEffects; oldPotionEffects = potionEffects;
} }
/**
* @return the old attribute bases
*/
public Map/*<Attribute, Double>*/ getOldAttributeBases() {
return oldAttributeBases;
}
/**
* @param attributeBases the old attribute bases to set
*/
public void setOldAttributeBases(Map/*<Attribute, Double>*/ attributeBases) {
oldAttributeBases = attributeBases;
}
/**
* @return the old attribute modifiers
*/
public Multimap/*<Attribute, AttributeModifier>*/ getOldAttributeMods() {
return oldAttributeMods;
}
/**
* @param attributeMods the old attribute modifiers to set
*/
public void setOldAttributeMods(Multimap/*<Attribute, AttributeModifier>*/ attributeMods) {
oldAttributeMods = attributeMods;
}
/** /**
* @return if the player was collidable * @return if the player was collidable
*/ */
@ -503,7 +524,6 @@ public class DPlayerData extends DREConfig {
oldLvl = config.getInt(PREFIX_STATE_PERSISTENCE + "oldLvl"); oldLvl = config.getInt(PREFIX_STATE_PERSISTENCE + "oldLvl");
oldExp = config.getInt(PREFIX_STATE_PERSISTENCE + "oldExp"); oldExp = config.getInt(PREFIX_STATE_PERSISTENCE + "oldExp");
oldMaxHealth = config.getDouble(PREFIX_STATE_PERSISTENCE + "oldMaxHealth");
oldHealth = config.getDouble(PREFIX_STATE_PERSISTENCE + "oldHealth"); oldHealth = config.getDouble(PREFIX_STATE_PERSISTENCE + "oldHealth");
oldFoodLevel = config.getInt(PREFIX_STATE_PERSISTENCE + "oldFoodLevel"); oldFoodLevel = config.getInt(PREFIX_STATE_PERSISTENCE + "oldFoodLevel");
oldFireTicks = config.getInt(PREFIX_STATE_PERSISTENCE + "oldFireTicks"); oldFireTicks = config.getInt(PREFIX_STATE_PERSISTENCE + "oldFireTicks");
@ -515,6 +535,34 @@ public class DPlayerData extends DREConfig {
} }
oldPotionEffects = (Collection<PotionEffect>) config.get(PREFIX_STATE_PERSISTENCE + "oldPotionEffects"); oldPotionEffects = (Collection<PotionEffect>) config.get(PREFIX_STATE_PERSISTENCE + "oldPotionEffects");
if (is1_9) {
Map<String, Object> basesMap = ConfigUtil.getMap(config, PREFIX_STATE_PERSISTENCE + "oldAttributeBases", false);
if (basesMap != null) {
oldAttributeBases = new HashMap<>();
for (Entry<String, Object> entry : basesMap.entrySet()) {
if (!(entry.getValue() instanceof Double)) {
continue;
}
Attribute attribute = EnumUtil.getEnum(Attribute.class, entry.getKey());
Double base = (Double) entry.getValue();
oldAttributeBases.put(attribute, base);
}
}
Map<String, Object> modsMap = ConfigUtil.getMap(config, PREFIX_STATE_PERSISTENCE + "oldAttributeModifiers", false);
if (modsMap != null) {
oldAttributeMods = HashMultimap.create();
for (Entry<String, Object> entry : modsMap.entrySet()) {
if (!(entry.getValue() instanceof Collection)) {
continue;
}
Attribute attribute = EnumUtil.getEnum(Attribute.class, entry.getKey());
Collection<AttributeModifier> mods = (Collection<AttributeModifier>) entry.getValue();
oldAttributeMods.putAll(attribute, mods);
}
}
}
try { try {
oldLocation = (Location) config.get(PREFIX_STATE_PERSISTENCE + "oldLocation"); oldLocation = (Location) config.get(PREFIX_STATE_PERSISTENCE + "oldLocation");
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
@ -544,9 +592,6 @@ public class DPlayerData extends DREConfig {
oldGameMode = player.getGameMode(); oldGameMode = player.getGameMode();
oldFireTicks = player.getFireTicks(); oldFireTicks = player.getFireTicks();
oldFoodLevel = player.getFoodLevel(); oldFoodLevel = player.getFoodLevel();
if (is1_9) {
oldMaxHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue();
}
oldHealth = player.getHealth(); oldHealth = player.getHealth();
oldExp = player.getExp(); oldExp = player.getExp();
oldLvl = player.getLevel(); oldLvl = player.getLevel();
@ -558,6 +603,18 @@ public class DPlayerData extends DREConfig {
oldLocation = player.getLocation(); oldLocation = player.getLocation();
oldPotionEffects = player.getActivePotionEffects(); oldPotionEffects = player.getActivePotionEffects();
if (is1_9) { if (is1_9) {
oldAttributeBases = new HashMap<>();
oldAttributeMods = HashMultimap.create();
for (Attribute attribute : Attribute.values()) {
AttributeInstance instance = player.getAttribute(attribute);
if (instance == null) {
continue;
}
oldAttributeBases.put(attribute, instance.getBaseValue());
for (AttributeModifier mod : instance.getModifiers()) {
oldAttributeMods.put(attribute, mod);
}
}
oldCollidabilityState = player.isCollidable(); oldCollidabilityState = player.isCollidable();
oldInvulnerabilityState = player.isInvulnerable(); oldInvulnerabilityState = player.isInvulnerable();
} }
@ -566,7 +623,6 @@ public class DPlayerData extends DREConfig {
config.set(PREFIX_STATE_PERSISTENCE + "oldGameMode", oldGameMode.toString()); config.set(PREFIX_STATE_PERSISTENCE + "oldGameMode", oldGameMode.toString());
config.set(PREFIX_STATE_PERSISTENCE + "oldFireTicks", oldFireTicks); config.set(PREFIX_STATE_PERSISTENCE + "oldFireTicks", oldFireTicks);
config.set(PREFIX_STATE_PERSISTENCE + "oldFoodLevel", oldFoodLevel); config.set(PREFIX_STATE_PERSISTENCE + "oldFoodLevel", oldFoodLevel);
config.set(PREFIX_STATE_PERSISTENCE + "oldMaxHealth", oldMaxHealth);
config.set(PREFIX_STATE_PERSISTENCE + "oldHealth", oldHealth); config.set(PREFIX_STATE_PERSISTENCE + "oldHealth", oldHealth);
config.set(PREFIX_STATE_PERSISTENCE + "oldExp", oldExp); config.set(PREFIX_STATE_PERSISTENCE + "oldExp", oldExp);
config.set(PREFIX_STATE_PERSISTENCE + "oldLvl", oldLvl); config.set(PREFIX_STATE_PERSISTENCE + "oldLvl", oldLvl);
@ -575,6 +631,10 @@ public class DPlayerData extends DREConfig {
config.set(PREFIX_STATE_PERSISTENCE + "oldOffHand", oldOffHand); config.set(PREFIX_STATE_PERSISTENCE + "oldOffHand", oldOffHand);
config.set(PREFIX_STATE_PERSISTENCE + "oldLocation", oldLocation); config.set(PREFIX_STATE_PERSISTENCE + "oldLocation", oldLocation);
config.set(PREFIX_STATE_PERSISTENCE + "oldPotionEffects", oldPotionEffects); config.set(PREFIX_STATE_PERSISTENCE + "oldPotionEffects", oldPotionEffects);
if (is1_9) {
config.set(PREFIX_STATE_PERSISTENCE + "oldAttributeBases", oldAttributeBases);
config.set(PREFIX_STATE_PERSISTENCE + "oldAttributeMods", oldAttributeMods.asMap());
}
config.set(PREFIX_STATE_PERSISTENCE + "oldCollidabilityState", oldCollidabilityState); config.set(PREFIX_STATE_PERSISTENCE + "oldCollidabilityState", oldCollidabilityState);
config.set(PREFIX_STATE_PERSISTENCE + "oldFlyingState", oldFlyingState); config.set(PREFIX_STATE_PERSISTENCE + "oldFlyingState", oldFlyingState);
config.set(PREFIX_STATE_PERSISTENCE + "oldInvulnerabilityState", oldInvulnerabilityState); config.set(PREFIX_STATE_PERSISTENCE + "oldInvulnerabilityState", oldInvulnerabilityState);
@ -589,7 +649,6 @@ public class DPlayerData extends DREConfig {
oldGameMode = null; oldGameMode = null;
oldFireTicks = 0; oldFireTicks = 0;
oldFoodLevel = 0; oldFoodLevel = 0;
oldMaxHealth = 20;
oldHealth = 0; oldHealth = 0;
oldExp = 0; oldExp = 0;
oldLvl = 0; oldLvl = 0;
@ -598,6 +657,8 @@ public class DPlayerData extends DREConfig {
oldOffHand = null; oldOffHand = null;
oldLocation = null; oldLocation = null;
oldPotionEffects = null; oldPotionEffects = null;
oldAttributeBases = null;
oldAttributeMods = null;
oldCollidabilityState = true; oldCollidabilityState = true;
oldFlyingState = false; oldFlyingState = false;
oldInvulnerabilityState = false; oldInvulnerabilityState = false;

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2012-2020 Frank Baumann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.erethon.dungeonsxl.util;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.bukkit.attribute.Attribute;
import static org.bukkit.attribute.Attribute.*;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Player;
/**
* @author Daniel Saukel
*/
public class AttributeUtil {
private static final Map<Attribute, Double> DEFAULT_PLAYER_VALUES = ImmutableMap.of(
GENERIC_MOVEMENT_SPEED, .1, // .7
GENERIC_ATTACK_DAMAGE, 1.0 // 2.0
);
/**
* Returns the default value that a player entity has.
*
* @param attribute the attribute instance to check
* @return the default value that a player entity has
*/
public static final Double getDefaultPlayerValue(AttributeInstance attribute) {
return DEFAULT_PLAYER_VALUES.getOrDefault(attribute.getAttribute(), attribute.getDefaultValue());
}
/**
* Resets a player's attributes.
*
* @param player the player
*/
public static void resetPlayerAttributes(Player player) {
for (Attribute attribute : Attribute.values()) {
AttributeInstance instance = player.getAttribute(attribute);
if (instance == null) {
continue;
}
instance.setBaseValue(getDefaultPlayerValue(instance));
instance.getModifiers().forEach(instance::removeModifier);
}
}
}