forked from Upstream/mmocore
party exp splitting
This commit is contained in:
parent
1fc6bdc945
commit
2d4a3cd3bd
@ -39,6 +39,7 @@ import net.Indyuce.mmocore.manager.profession.*;
|
||||
import net.Indyuce.mmocore.manager.social.BoosterManager;
|
||||
import net.Indyuce.mmocore.manager.social.PartyManager;
|
||||
import net.Indyuce.mmocore.manager.social.RequestManager;
|
||||
import net.Indyuce.mmocore.skill.cast.listener.SkillBar;
|
||||
import net.Indyuce.mmocore.skill.list.Ambers;
|
||||
import net.Indyuce.mmocore.skill.list.Neptune_Gift;
|
||||
import net.Indyuce.mmocore.skill.list.Sneaky_Picky;
|
||||
@ -236,7 +237,6 @@ public class MMOCore extends LuminePlugin {
|
||||
Bukkit.getPluginManager().registerEvents(new GoldPouchesListener(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new BlockListener(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new LootableChestsListener(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new SpellCast(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new PartyListener(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new GuildListener(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new FishingListener(), this);
|
||||
|
@ -6,7 +6,9 @@ import io.lumine.mythic.lib.player.cooldown.CooldownMap;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigMessage;
|
||||
import net.Indyuce.mmocore.api.Waypoint;
|
||||
import net.Indyuce.mmocore.api.event.*;
|
||||
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
|
||||
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
|
||||
@ -24,10 +26,10 @@ import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.PlayerProfessions;
|
||||
import net.Indyuce.mmocore.listener.SpellCast.SkillCasting;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import net.Indyuce.mmocore.skill.cast.listener.SkillBar.SkillCasting;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.*;
|
||||
@ -485,7 +487,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
* @param source How the player earned experience
|
||||
*/
|
||||
public void giveExperience(int value, EXPSource source) {
|
||||
giveExperience(value, source, null);
|
||||
giveExperience(value, source, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -495,8 +497,9 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
* @param source How the player earned experience
|
||||
* @param hologramLocation Location used to display the hologram. If it's null, no
|
||||
* hologram will be displayed
|
||||
* @param splitExp Should the exp be split among party members
|
||||
*/
|
||||
public void giveExperience(double value, EXPSource source, @Nullable Location hologramLocation) {
|
||||
public void giveExperience(double value, EXPSource source, @Nullable Location hologramLocation, boolean splitExp) {
|
||||
if (hasReachedMaxLevel()) {
|
||||
setExperience(0);
|
||||
return;
|
||||
@ -509,6 +512,14 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
value = MMOCore.plugin.boosterManager.calculateExp(null, value);
|
||||
value *= 1 + getStats().getStat(StatType.ADDITIONAL_EXPERIENCE) / 100;
|
||||
|
||||
// Splitting exp through party members
|
||||
if (splitExp && hasParty()) {
|
||||
List<PlayerData> onlineMembers = getParty().getOnlineMembers();
|
||||
value /= onlineMembers.size();
|
||||
for (PlayerData member : onlineMembers)
|
||||
member.giveExperience(value, EXPSource.PARTY_SHARING, null, false);
|
||||
}
|
||||
|
||||
PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, (int) value, source);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled())
|
||||
@ -678,7 +689,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
|
||||
/**
|
||||
* @return If the action bar is not being used to display anything else
|
||||
* i.e if the "general info" action bar can be displayed
|
||||
* i.e if the "general info" action bar can be displayed
|
||||
*/
|
||||
public boolean canSeeActionBar() {
|
||||
return actionBarTimeOut < System.currentTimeMillis();
|
||||
@ -825,7 +836,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
* checks if they could potentially upgrade to one of these
|
||||
*
|
||||
* @return If the player can change its current class to
|
||||
* a subclass
|
||||
* a subclass
|
||||
*/
|
||||
public boolean canChooseSubclass() {
|
||||
for (Subclass subclass : getProfess().getSubclasses())
|
||||
|
@ -12,7 +12,7 @@ import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Party {
|
||||
private final PartyMembers members = new PartyMembers();
|
||||
private final List<PlayerData> members = new ArrayList<>();
|
||||
private final Map<UUID, Long> invites = new HashMap<>();
|
||||
|
||||
// used to check if two parties are the same
|
||||
@ -36,10 +36,24 @@ public class Party {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public PartyMembers getMembers() {
|
||||
public List<PlayerData> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
public List<PlayerData> getOnlineMembers() {
|
||||
List<PlayerData> online = new ArrayList<>();
|
||||
|
||||
for (PlayerData member : members)
|
||||
if (member.isOnline())
|
||||
online.add(member);
|
||||
|
||||
return online;
|
||||
}
|
||||
|
||||
public PlayerData getMember(int index) {
|
||||
return members.get(index);
|
||||
}
|
||||
|
||||
public long getLastInvite(Player player) {
|
||||
return invites.containsKey(player.getUniqueId()) ? invites.get(player.getUniqueId()) : 0;
|
||||
}
|
||||
@ -48,6 +62,21 @@ public class Party {
|
||||
invites.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean hasMember(PlayerData playerData) {
|
||||
return hasMember(playerData.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean hasMember(Player player) {
|
||||
return hasMember(player.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean hasMember(UUID uuid) {
|
||||
for (PlayerData member : members)
|
||||
if (member.getUniqueId().equals(uuid))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeMember(PlayerData data) {
|
||||
removeMember(data, true);
|
||||
}
|
||||
@ -59,11 +88,12 @@ public class Party {
|
||||
|
||||
members.remove(data);
|
||||
data.setParty(null);
|
||||
|
||||
reopenInventories();
|
||||
clearStatBonuses(data);
|
||||
members.forEach(this::applyStatBonuses);
|
||||
updateOpenInventories();
|
||||
|
||||
// Disband the party if no member left
|
||||
if (members.count() < 1) {
|
||||
if (members.size() < 1) {
|
||||
MMOCore.plugin.partyManager.unregisterParty(this);
|
||||
return;
|
||||
}
|
||||
@ -82,18 +112,24 @@ public class Party {
|
||||
|
||||
data.setParty(this);
|
||||
members.add(data);
|
||||
members.forEach(this::applyStatBonuses);
|
||||
|
||||
reopenInventories();
|
||||
updateOpenInventories();
|
||||
}
|
||||
|
||||
public void reopenInventories() {
|
||||
for (PlayerData member : members.members)
|
||||
private void updateOpenInventories() {
|
||||
for (PlayerData member : members)
|
||||
if (member.isOnline() && member.getPlayer().getOpenInventory() != null
|
||||
&& member.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof PartyViewInventory)
|
||||
((PluginInventory) member.getPlayer().getOpenInventory().getTopInventory().getHolder()).open();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void sendPartyInvite(PlayerData inviter, PlayerData target) {
|
||||
sendInvite(inviter, target);
|
||||
}
|
||||
|
||||
public void sendInvite(PlayerData inviter, PlayerData target) {
|
||||
invites.put(target.getUniqueId(), System.currentTimeMillis());
|
||||
Request request = new PartyInvite(this, inviter, target);
|
||||
if (inviter.isOnline() && target.isOnline())
|
||||
@ -102,61 +138,36 @@ public class Party {
|
||||
MMOCore.plugin.requestManager.registerRequest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* An issue can happen if the consumer given as parameter
|
||||
* modifies the member list during list iteration.
|
||||
* <p>
|
||||
* To solve this, this method first copies the member list
|
||||
* and iterates through it to avoid the exception.
|
||||
*/
|
||||
public void forEachMember(Consumer<PlayerData> action) {
|
||||
new ArrayList<>(members).forEach(action);
|
||||
}
|
||||
|
||||
private static final String PARTY_BUFF_MODIFIER_KEY = "mmocoreParty";
|
||||
|
||||
/**
|
||||
* Applies party stat bonuses to a specific player
|
||||
*/
|
||||
private void applyStatBonuses(PlayerData player) {
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).addModifier(PARTY_BUFF_MODIFIER_KEY,
|
||||
MMOCore.plugin.partyManager.getBonus(stat).multiply(members.size() - 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear party stat bonuses from a player
|
||||
*/
|
||||
private void clearStatBonuses(PlayerData player) {
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).remove(PARTY_BUFF_MODIFIER_KEY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Party && ((Party) obj).getUniqueId().equals(getUniqueId());
|
||||
}
|
||||
|
||||
/*
|
||||
* this class makes controling entries and departures and APPLYING PARTY
|
||||
* STAT ATTRIBUTES much easier
|
||||
*/
|
||||
public static class PartyMembers {
|
||||
private final List<PlayerData> members = new ArrayList<>();
|
||||
|
||||
public PlayerData get(int count) {
|
||||
return members.get(count);
|
||||
}
|
||||
|
||||
public boolean has(PlayerData player) {
|
||||
return members.contains(player);
|
||||
}
|
||||
|
||||
public boolean has(Player player) {
|
||||
for (PlayerData member : members)
|
||||
if (member.getUniqueId().equals(player.getUniqueId()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void add(PlayerData player) {
|
||||
members.add(player);
|
||||
|
||||
members.forEach(this::applyAttributes);
|
||||
}
|
||||
|
||||
public void remove(PlayerData player) {
|
||||
members.remove(player);
|
||||
|
||||
members.forEach(this::applyAttributes);
|
||||
clearAttributes(player);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super PlayerData> action) {
|
||||
members.forEach(action);
|
||||
}
|
||||
|
||||
public int count() {
|
||||
return members.size();
|
||||
}
|
||||
|
||||
private void applyAttributes(PlayerData player) {
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).addModifier("mmocoreParty",
|
||||
MMOCore.plugin.partyManager.getBonus(stat).multiply(members.size() - 1)));
|
||||
}
|
||||
|
||||
private void clearAttributes(PlayerData player) {
|
||||
MMOCore.plugin.partyManager.getBonuses().forEach(stat -> player.getStats().getInstance(stat).remove("mmocoreParty"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class PartyInvite extends Request {
|
||||
}
|
||||
|
||||
public void accept() {
|
||||
if(party.getMembers().count() >= Math.min(8, Math.max(2, MMOCore.plugin.getConfig().getInt("party.max-players", 8)))) {
|
||||
if(party.getMembers().size() >= Math.max(2, MMOCore.plugin.getConfig().getInt("party.max-players", 8))) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("party-is-full").send(target.getPlayer());
|
||||
return;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public class MMOCoreTargetRestriction implements TargetRestriction {
|
||||
PlayerData targetData = PlayerData.get(target.getUniqueId());
|
||||
|
||||
// Check for the same party
|
||||
if (targetData.hasParty() && targetData.getParty().getMembers().has(player))
|
||||
if (targetData.hasParty() && targetData.getParty().hasMember(player))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
.getLevelUpExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase());
|
||||
|
||||
else if (identifier.startsWith("party_count"))
|
||||
return playerData.hasParty() ? String.valueOf(playerData.getParty().getMembers().count()) : "0";
|
||||
return playerData.hasParty() ? String.valueOf(playerData.getParty().getMembers().size()) : "0";
|
||||
|
||||
else if (identifier.startsWith("profession_"))
|
||||
return String
|
||||
|
@ -17,6 +17,11 @@ public enum EXPSource {
|
||||
*/
|
||||
VANILLA,
|
||||
|
||||
/**
|
||||
* When party members share exp
|
||||
*/
|
||||
PARTY_SHARING,
|
||||
|
||||
/**
|
||||
* When using the experience trigger. Keep in mind the
|
||||
* experience trigger can also use another experience source
|
||||
|
@ -176,7 +176,7 @@ public class PlayerStats extends EditableInventory {
|
||||
public Placeholders getPlaceholders(GeneratedInventory inv, int n) {
|
||||
Placeholders holders = new Placeholders();
|
||||
|
||||
int count = inv.getPlayerData().getParty().getMembers().count();
|
||||
int count = inv.getPlayerData().getParty().getMembers().size();
|
||||
holders.register("count", "" + count);
|
||||
for (StatType stat : MMOCore.plugin.partyManager.getBonuses())
|
||||
holders.register("buff_" + stat.name().toLowerCase(), MMOCore.plugin.partyManager.getBonus(stat).multiply(count - 1).toString());
|
||||
@ -186,7 +186,7 @@ public class PlayerStats extends EditableInventory {
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(GeneratedInventory inv) {
|
||||
return inv.getPlayerData().hasParty() && inv.getPlayerData().getParty().getMembers().count() > 1;
|
||||
return inv.getPlayerData().hasParty() && inv.getPlayerData().getParty().getMembers().size() > 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ import net.Indyuce.mmocore.api.util.input.PlayerInput.InputType;
|
||||
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
|
||||
import net.Indyuce.mmocore.gui.api.EditableInventory;
|
||||
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
|
||||
import net.Indyuce.mmocore.gui.api.PluginInventory;
|
||||
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
|
||||
import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
||||
@ -98,7 +97,7 @@ public class EditablePartyView extends EditableInventory {
|
||||
|
||||
@Override
|
||||
public ItemStack display(GeneratedInventory inv, int n) {
|
||||
return inv.getPlayerData().getParty().getMembers().count() > n ? member.display(inv, n) : empty.display(inv, n);
|
||||
return inv.getPlayerData().getParty().getMembers().size() > n ? member.display(inv, n) : empty.display(inv, n);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -127,7 +126,7 @@ public class EditablePartyView extends EditableInventory {
|
||||
|
||||
@Override
|
||||
public String calculateName() {
|
||||
return getName().replace("{max}", "" + max).replace("{players}", "" + getPlayerData().getParty().getMembers().count());
|
||||
return getName().replace("{max}", "" + max).replace("{players}", "" + getPlayerData().getParty().getMembers().size());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -142,7 +141,7 @@ public class EditablePartyView extends EditableInventory {
|
||||
|
||||
if (item.getFunction().equals("invite")) {
|
||||
|
||||
if (playerData.getParty().getMembers().count() >= max) {
|
||||
if (playerData.getParty().getMembers().size() >= max) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("party-is-full").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1);
|
||||
return;
|
||||
@ -165,14 +164,14 @@ public class EditablePartyView extends EditableInventory {
|
||||
}
|
||||
|
||||
PlayerData targetData = PlayerData.get(target);
|
||||
if (playerData.getParty().getMembers().has(targetData)) {
|
||||
if (playerData.getParty().hasMember(targetData)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("already-in-party", "player", target.getName()).send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
playerData.getParty().sendPartyInvite(playerData, targetData);
|
||||
playerData.getParty().sendInvite(playerData, targetData);
|
||||
MMOCore.plugin.configManager.getSimpleMessage("sent-party-invite", "player", target.getName()).send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1);
|
||||
open();
|
||||
|
@ -54,7 +54,7 @@ public class PartyListener implements Listener {
|
||||
LivingEntity entity = event.getEntity();
|
||||
if (entity instanceof Player && !entity.hasMetadata("NPC")) {
|
||||
PlayerData targetData = PlayerData.get((Player) event.getEntity());
|
||||
if (targetData.hasParty() && targetData.getParty().getMembers().has(PlayerData.get(event.getData().getUniqueId())))
|
||||
if (targetData.hasParty() && targetData.getParty().hasMember(PlayerData.get(event.getData().getUniqueId())))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.social.Party;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.manager.MMOCoreManager;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -34,7 +35,8 @@ public class PartyManager implements MMOCoreManager {
|
||||
|
||||
public void unregisterParty(Party party) {
|
||||
// IMPORTANT: clears all party members before unregistering the party
|
||||
party.getMembers().forEach(party::removeMember);
|
||||
party.forEachMember(party::removeMember);
|
||||
Validate.isTrue(party.getMembers().isEmpty(), "Tried unregistering a non-empty party");
|
||||
parties.remove(party);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user