Moving Stuff around pt 2

This commit is contained in:
nossr50
2019-02-09 22:37:22 -08:00
parent 4d4dad0ccb
commit e749d5eb7f
282 changed files with 1547 additions and 1541 deletions

View File

@ -0,0 +1,88 @@
package com.gmail.nossr50.core.api;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.SuperAbilityType;
import com.gmail.nossr50.runnables.skills.BleedTimerTask;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
public final class AbilityAPI {
private AbilityAPI() {}
public static boolean berserkEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.BERSERK);
}
public static boolean gigaDrillBreakerEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER);
}
public static boolean greenTerraEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.GREEN_TERRA);
}
public static boolean serratedStrikesEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.SERRATED_STRIKES);
}
public static boolean skullSplitterEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.SKULL_SPLITTER);
}
public static boolean superBreakerEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.SUPER_BREAKER);
}
public static boolean treeFellerEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.TREE_FELLER);
}
public static boolean isAnyAbilityEnabled(Player player) {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
for (SuperAbilityType ability : SuperAbilityType.values()) {
if (mcMMOPlayer.getAbilityMode(ability)) {
return true;
}
}
return false;
}
public static void resetCooldowns(Player player) {
UserManager.getPlayer(player).resetCooldowns();
}
public static void setBerserkCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.BERSERK, cooldown);
}
public static void setGigaDrillBreakerCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.GIGA_DRILL_BREAKER, cooldown);
}
public static void setGreenTerraCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.GREEN_TERRA, cooldown);
}
public static void setSerratedStrikesCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.SERRATED_STRIKES, cooldown);
}
public static void setSkullSplitterCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.SKULL_SPLITTER, cooldown);
}
public static void setSuperBreakerCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.SUPER_BREAKER, cooldown);
}
public static void setTreeFellerCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.TREE_FELLER, cooldown);
}
public static boolean isBleeding(LivingEntity entity) {
return BleedTimerTask.isBleeding(entity);
}
}

View File

@ -0,0 +1,153 @@
package com.gmail.nossr50.core.api;
import com.gmail.nossr50.chat.ChatManager;
import com.gmail.nossr50.chat.ChatManagerFactory;
import com.gmail.nossr50.chat.PartyChatManager;
import com.gmail.nossr50.core.datatypes.chat.ChatMode;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public final class ChatAPI {
private ChatAPI() {}
/**
* Send a message to all members of a party
* </br>
* This function is designed for API usage.
*
* @param plugin The plugin sending the message
* @param sender The name of the sender
* @param displayName The display name of the sender
* @param party The name of the party to send to
* @param message The message to send
*/
public static void sendPartyChat(Plugin plugin, String sender, String displayName, String party, String message) {
getPartyChatManager(plugin, party).handleChat(sender, displayName, message);
}
/**
* Send a message to all members of a party
* </br>
* This function is designed for API usage.
*
* @param plugin The plugin sending the message
* @param sender The name of the sender to display in the chat
* @param party The name of the party to send to
* @param message The message to send
*/
public static void sendPartyChat(Plugin plugin, String sender, String party, String message) {
getPartyChatManager(plugin, party).handleChat(sender, message);
}
/**
* Send a message to administrators
* </br>
* This function is designed for API usage.
*
* @param plugin The plugin sending the message
* @param sender The name of the sender
* @param displayName The display name of the sender
* @param message The message to send
*/
public static void sendAdminChat(Plugin plugin, String sender, String displayName, String message) {
ChatManagerFactory.getChatManager(plugin, ChatMode.ADMIN).handleChat(sender, displayName, message);
}
/**
* Send a message to administrators
* </br>
* This function is designed for API usage.
*
* @param plugin The plugin sending the message
* @param sender The name of the sender to display in the chat
* @param message The message to send
*/
public static void sendAdminChat(Plugin plugin, String sender, String message) {
ChatManagerFactory.getChatManager(plugin, ChatMode.ADMIN).handleChat(sender, message);
}
/**
* Check if a player is currently talking in party chat.
*
* @param player The player to check
* @return true if the player is using party chat, false otherwise
*/
public static boolean isUsingPartyChat(Player player) {
return UserManager.getPlayer(player).isChatEnabled(ChatMode.PARTY);
}
/**
* Check if a player is currently talking in party chat.
*
* @param playerName The name of the player to check
* @return true if the player is using party chat, false otherwise
*/
public static boolean isUsingPartyChat(String playerName) {
return UserManager.getPlayer(playerName).isChatEnabled(ChatMode.PARTY);
}
/**
* Check if a player is currently talking in admin chat.
*
* @param player The player to check
* @return true if the player is using admin chat, false otherwise
*/
public static boolean isUsingAdminChat(Player player) {
return UserManager.getPlayer(player).isChatEnabled(ChatMode.ADMIN);
}
/**
* Check if a player is currently talking in admin chat.
*
* @param playerName The name of the player to check
* @return true if the player is using admin chat, false otherwise
*/
public static boolean isUsingAdminChat(String playerName) {
return UserManager.getPlayer(playerName).isChatEnabled(ChatMode.ADMIN);
}
/**
* Toggle the party chat mode of a player.
*
* @param player The player to toggle party chat on.
*/
public static void togglePartyChat(Player player) {
UserManager.getPlayer(player).toggleChat(ChatMode.PARTY);
}
/**
* Toggle the party chat mode of a player.
*
* @param playerName The name of the player to toggle party chat on.
*/
public static void togglePartyChat(String playerName) {
UserManager.getPlayer(playerName).toggleChat(ChatMode.PARTY);
}
/**
* Toggle the admin chat mode of a player.
*
* @param player The player to toggle admin chat on.
*/
public static void toggleAdminChat(Player player) {
UserManager.getPlayer(player).toggleChat(ChatMode.ADMIN);
}
/**
* Toggle the admin chat mode of a player.
*
* @param playerName The name of the player to toggle party chat on.
*/
public static void toggleAdminChat(String playerName) {
UserManager.getPlayer(playerName).toggleChat(ChatMode.ADMIN);
}
private static ChatManager getPartyChatManager(Plugin plugin, String party) {
ChatManager chatManager = ChatManagerFactory.getChatManager(plugin, ChatMode.PARTY);
((PartyChatManager) chatManager).setParty(PartyManager.getParty(party));
return chatManager;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,242 @@
package com.gmail.nossr50.core.api;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.core.datatypes.party.PartyLeader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.*;
public final class PartyAPI {
private PartyAPI() {}
/**
* Get the name of the party a player is in.
* </br>
* This function is designed for API usage.
*
* @param player The player to check the party name of
* @return the name of the player's party, or null if not in a party
*/
public static String getPartyName(Player player) {
if (!inParty(player)) {
return null;
}
return UserManager.getPlayer(player).getParty().getName();
}
/**
* Checks if a player is in a party.
* </br>
* This function is designed for API usage.
*
* @param player The player to check
* @return true if the player is in a party, false otherwise
*/
public static boolean inParty(Player player) {
return UserManager.getPlayer(player).inParty();
}
/**
* Check if two players are in the same party.
* </br>
* This function is designed for API usage.
*
* @param playera The first player to check
* @param playerb The second player to check
* @return true if the two players are in the same party, false otherwise
*/
public static boolean inSameParty(Player playera, Player playerb) {
return PartyManager.inSameParty(playera, playerb);
}
/**
* Get a list of all current parties.
* </br>
* This function is designed for API usage.
*
* @return the list of parties.
*/
public static List<Party> getParties() {
return PartyManager.getParties();
}
/**
* Add a player to a party.
* </br>
* This function is designed for API usage.
*
* @param player The player to add to the party
* @param partyName The party to add the player to
* @deprecated parties can have limits, use the other method
*/
@Deprecated
public static void addToParty(Player player, String partyName) {
Party party = PartyManager.getParty(partyName);
if (party == null) {
party = new Party(new PartyLeader(player.getUniqueId(), player.getName()), partyName);
} else {
if(PartyManager.isPartyFull(player, party))
{
NotificationManager.sendPlayerInformation(player, NotificationType.PARTY_MESSAGE, "Commands.Party.PartyFull", party.toString());
return;
}
}
PartyManager.addToParty(UserManager.getPlayer(player), party);
}
/**
* The max party size of the server
* 0 or less for no size limit
* @return the max party size on this server
*/
public static int getMaxPartySize()
{
return Config.getInstance().getPartyMaxSize();
}
/**
* Add a player to a party.
* </br>
* This function is designed for API usage.
*
* @param player The player to add to the party
* @param partyName The party to add the player to
* @param bypassLimit if true bypasses party size limits
*/
public static void addToParty(Player player, String partyName, boolean bypassLimit) {
Party party = PartyManager.getParty(partyName);
if (party == null) {
party = new Party(new PartyLeader(player.getUniqueId(), player.getName()), partyName);
}
PartyManager.addToParty(UserManager.getPlayer(player), party);
}
/**
* Remove a player from a party.
* </br>
* This function is designed for API usage.
*
* @param player The player to remove
*/
public static void removeFromParty(Player player) {
PartyManager.removeFromParty(UserManager.getPlayer(player));
}
/**
* Get the leader of a party.
* </br>
* This function is designed for API usage.
*
* @param partyName The party name
* @return the leader of the party
*/
public static String getPartyLeader(String partyName) {
return PartyManager.getPartyLeaderName(partyName);
}
/**
* Set the leader of a party.
* </br>
* This function is designed for API usage.
*
* @param partyName The name of the party to set the leader of
* @param playerName The playerName to set as leader
*/
@Deprecated
public static void setPartyLeader(String partyName, String playerName) {
PartyManager.setPartyLeader(mcMMO.p.getServer().getOfflinePlayer(playerName).getUniqueId(), PartyManager.getParty(partyName));
}
/**
* Get a list of all players in this player's party.
* </br>
* This function is designed for API usage.
*
* @param player The player to check
* @return all the players in the player's party
*/
@Deprecated
public static List<OfflinePlayer> getOnlineAndOfflineMembers(Player player) {
List<OfflinePlayer> members = new ArrayList<OfflinePlayer>();
for (UUID memberUniqueId : PartyManager.getAllMembers(player).keySet()) {
OfflinePlayer member = mcMMO.p.getServer().getOfflinePlayer(memberUniqueId);
members.add(member);
}
return members;
}
/**
* Get a list of all player names in this player's party.
* </br>
* This function is designed for API usage.
*
* @param player The player to check
* @return all the player names in the player's party
*/
@Deprecated
public static LinkedHashSet<String> getMembers(Player player) {
return (LinkedHashSet<String>) PartyManager.getAllMembers(player).values();
}
/**
* Get a list of all player names and uuids in this player's party.
* </br>
* This function is designed for API usage.
*
* @param player The player to check
* @return all the player names and uuids in the player's party
*/
public static LinkedHashMap<UUID, String> getMembersMap(Player player) {
return PartyManager.getAllMembers(player);
}
/**
* Get a list of all online players in this party.
* </br>
* This function is designed for API usage.
*
* @param partyName The party to check
* @return all online players in this party
*/
public static List<Player> getOnlineMembers(String partyName) {
return PartyManager.getOnlineMembers(partyName);
}
/**
* Get a list of all online players in this player's party.
* </br>
* This function is designed for API usage.
*
* @param player The player to check
* @return all online players in the player's party
*/
public static List<Player> getOnlineMembers(Player player) {
return PartyManager.getOnlineMembers(player);
}
public static boolean hasAlly(String partyName) {
return getAllyName(partyName) != null;
}
public static String getAllyName(String partyName) {
Party ally = PartyManager.getParty(partyName).getAlly();
if (ally != null) {
return ally.getName();
}
return null;
}
}

View File

@ -0,0 +1,93 @@
package com.gmail.nossr50.core.api;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public final class SkillAPI {
private SkillAPI() {}
/**
* Returns a list of strings with mcMMO's skills
* This includes parent and child skills
* </br>
* This function is designed for API usage.
*
* @return a list of strings with valid skill names
*/
public static List<String> getSkills() {
return getListFromEnum(Arrays.asList(PrimarySkillType.values()));
}
/**
* Returns a list of strings with mcMMO's skills
* This only includes parent skills
* </br>
* This function is designed for API usage.
*
* @return a list of strings with valid skill names
*/
public static List<String> getNonChildSkills() {
return getListFromEnum(PrimarySkillType.NON_CHILD_SKILLS);
}
/**
* Returns a list of strings with mcMMO's skills
* This only includes child skills
* </br>
* This function is designed for API usage.
*
* @return a list of strings with valid skill names
*/
public static List<String> getChildSkills() {
return getListFromEnum(PrimarySkillType.CHILD_SKILLS);
}
/**
* Returns a list of strings with mcMMO's skills
* This only includes combat skills
* </br>
* This function is designed for API usage.
*
* @return a list of strings with valid skill names
*/
public static List<String> getCombatSkills() {
return getListFromEnum(PrimarySkillType.COMBAT_SKILLS);
}
/**
* Returns a list of strings with mcMMO's skills
* This only includes gathering skills
* </br>
* This function is designed for API usage.
*
* @return a list of strings with valid skill names
*/
public static List<String> getGatheringSkills() {
return getListFromEnum(PrimarySkillType.GATHERING_SKILLS);
}
/**
* Returns a list of strings with mcMMO's skills
* This only includes misc skills
* </br>
* This function is designed for API usage.
*
* @return a list of strings with valid skill names
*/
public static List<String> getMiscSkills() {
return getListFromEnum(PrimarySkillType.MISC_SKILLS);
}
private static List<String> getListFromEnum(List<PrimarySkillType> skillsTypes) {
List<String> skills = new ArrayList<String>();
for (PrimarySkillType primarySkillType : skillsTypes) {
skills.add(primarySkillType.name());
}
return skills;
}
}

View File

@ -0,0 +1,9 @@
package com.gmail.nossr50.core.api.exceptions;
public class InvalidFormulaTypeException extends RuntimeException {
private static final long serialVersionUID = 3368670229490121886L;
public InvalidFormulaTypeException() {
super("That is not a valid FormulaType.");
}
}

View File

@ -0,0 +1,9 @@
package com.gmail.nossr50.core.api.exceptions;
public class InvalidPlayerException extends RuntimeException {
private static final long serialVersionUID = 907213002618581385L;
public InvalidPlayerException() {
super("That player does not exist in the database.");
}
}

View File

@ -0,0 +1,9 @@
package com.gmail.nossr50.core.api.exceptions;
public class InvalidSkillException extends RuntimeException {
private static final long serialVersionUID = 942705284195791157L;
public InvalidSkillException() {
super("That is not a valid skill.");
}
}

View File

@ -0,0 +1,9 @@
package com.gmail.nossr50.core.api.exceptions;
public class InvalidXPGainReasonException extends RuntimeException {
private static final long serialVersionUID = 4427052841957931157L;
public InvalidXPGainReasonException() {
super("That is not a valid XPGainReason.");
}
}

View File

@ -0,0 +1,11 @@
package com.gmail.nossr50.core.api.exceptions;
import org.bukkit.entity.Player;
public class McMMOPlayerNotFoundException extends RuntimeException {
private static final long serialVersionUID = 761917904993202836L;
public McMMOPlayerNotFoundException(Player player) {
super("McMMOPlayer object was not found for: " + player.getName() + " " + player.getUniqueId());
}
}

View File

@ -0,0 +1,21 @@
package com.gmail.nossr50.core.chat;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.events.chat.McMMOAdminChatEvent;
import org.bukkit.plugin.Plugin;
public class AdminChatManager extends ChatManager {
protected AdminChatManager(Plugin plugin) {
super(plugin, Config.getInstance().getAdminDisplayNames(), Config.getInstance().getAdminChatPrefix());
}
@Override
public void handleChat(String senderName, String displayName, String message, boolean isAsync) {
handleChat(new McMMOAdminChatEvent(plugin, senderName, displayName, message, isAsync));
}
@Override
protected void sendMessage() {
plugin.getServer().broadcast(message, "mcmmo.chat.adminchat");
}
}

View File

@ -0,0 +1,85 @@
package com.gmail.nossr50.core.chat;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.events.chat.McMMOChatEvent;
import com.gmail.nossr50.events.chat.McMMOPartyChatEvent;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public abstract class ChatManager {
protected Plugin plugin;
protected boolean useDisplayNames;
protected String chatPrefix;
protected String senderName;
protected String displayName;
protected String message;
protected ChatManager(Plugin plugin, boolean useDisplayNames, String chatPrefix) {
this.plugin = plugin;
this.useDisplayNames = useDisplayNames;
this.chatPrefix = chatPrefix;
}
protected void handleChat(McMMOChatEvent event) {
plugin.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
senderName = event.getSender();
displayName = useDisplayNames ? event.getDisplayName() : senderName;
message = LocaleLoader.formatString(chatPrefix, displayName) + " " + event.getMessage();
sendMessage();
/*
* Party Chat Spying
* Party messages will be copied to people with the mcmmo.admin.chatspy permission node
*/
if(event instanceof McMMOPartyChatEvent)
{
//We need to grab the party chat name
McMMOPartyChatEvent partyChatEvent = (McMMOPartyChatEvent) event;
//Find the people with permissions
for(Player player : event.getPlugin().getServer().getOnlinePlayers())
{
//Check for toggled players
if(UserManager.getPlayer(player).isPartyChatSpying())
{
Party adminParty = UserManager.getPlayer(player).getParty();
//Only message admins not part of this party
if(adminParty != null)
{
//TODO: Incorporate JSON
if(!adminParty.getName().equalsIgnoreCase(partyChatEvent.getParty()))
player.sendMessage(LocaleLoader.getString("Commands.AdminChatSpy.Chat", partyChatEvent.getParty(), message));
} else {
player.sendMessage(LocaleLoader.getString("Commands.AdminChatSpy.Chat", partyChatEvent.getParty(), message));
}
}
}
}
}
public void handleChat(String senderName, String message) {
handleChat(senderName, senderName, message, false);
}
public void handleChat(Player player, String message, boolean isAsync) {
handleChat(player.getName(), player.getDisplayName(), message, isAsync);
}
public void handleChat(String senderName, String displayName, String message) {
handleChat(senderName, displayName, message, false);
}
public abstract void handleChat(String senderName, String displayName, String message, boolean isAsync);
protected abstract void sendMessage();
}

View File

@ -0,0 +1,30 @@
package com.gmail.nossr50.core.chat;
import com.gmail.nossr50.core.datatypes.chat.ChatMode;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
public class ChatManagerFactory {
private static final HashMap<Plugin, AdminChatManager> adminChatManagers = new HashMap<Plugin, AdminChatManager>();
private static final HashMap<Plugin, PartyChatManager> partyChatManagers = new HashMap<Plugin, PartyChatManager>();
public static ChatManager getChatManager(Plugin plugin, ChatMode mode) {
switch (mode) {
case ADMIN:
if (!adminChatManagers.containsKey(plugin)) {
adminChatManagers.put(plugin, new AdminChatManager(plugin));
}
return adminChatManagers.get(plugin);
case PARTY:
if (!partyChatManagers.containsKey(plugin)) {
partyChatManagers.put(plugin, new PartyChatManager(plugin));
}
return partyChatManagers.get(plugin);
default:
return null;
}
}
}

View File

@ -0,0 +1,29 @@
package com.gmail.nossr50.core.chat;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.events.chat.McMMOPartyChatEvent;
import com.gmail.nossr50.core.runnables.party.PartyChatTask;
import org.bukkit.plugin.Plugin;
public class PartyChatManager extends ChatManager {
private Party party;
protected PartyChatManager(Plugin plugin) {
super(plugin, Config.getInstance().getPartyDisplayNames(), Config.getInstance().getPartyChatPrefix());
}
public void setParty(Party party) {
this.party = party;
}
@Override
public void handleChat(String senderName, String displayName, String message, boolean isAsync) {
handleChat(new McMMOPartyChatEvent(plugin, senderName, displayName, party.getName(), message, isAsync));
}
@Override
protected void sendMessage() {
new PartyChatTask(plugin, party, senderName, displayName, message).runTask(plugin);
}
}

View File

@ -1,7 +1,7 @@
package com.gmail.nossr50.core.datatypes.experience;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.core.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

View File

@ -8,12 +8,12 @@ import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.party.PartyTeleportRecord;
import com.gmail.nossr50.core.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.core.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SuperAbilityType;
import com.gmail.nossr50.core.datatypes.chat.ChatMode;
import com.gmail.nossr50.core.datatypes.mods.CustomTool;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.core.datatypes.skills.ToolType;
import com.gmail.nossr50.core.skills.ToolType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.PartyManager;

View File

@ -5,9 +5,9 @@ import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.core.datatypes.experience.FormulaType;
import com.gmail.nossr50.core.datatypes.experience.SkillXpGain;
import com.gmail.nossr50.core.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.core.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.core.datatypes.MobHealthbarType;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SuperAbilityType;
import com.gmail.nossr50.core.skills.MobHealthbarType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.player.PlayerProfileSaveTask;
import com.gmail.nossr50.skills.child.FamilyTree;

View File

@ -0,0 +1,142 @@
package com.gmail.nossr50.core.locale;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.mcMMO;
import org.bukkit.ChatColor;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
public final class LocaleLoader {
private static final String BUNDLE_ROOT = "com.com.gmail.com.gmail.nossr50.locale.locale";
private static ResourceBundle bundle = null;
private static ResourceBundle enBundle = null;
private LocaleLoader() {};
public static String getString(String key) {
return getString(key, (Object[]) null);
}
/**
* Gets the appropriate string from the Locale files.
*
* @param key The key to look up the string with
* @param messageArguments Any arguments to be added to the string
* @return The properly formatted locale string
*/
public static String getString(String key, Object... messageArguments) {
if (bundle == null) {
initialize();
}
try {
return getString(key, bundle, messageArguments);
}
catch (MissingResourceException ex) {
try {
return getString(key, enBundle, messageArguments);
}
catch (MissingResourceException ex2) {
if (!key.contains("Guides")) {
mcMMO.p.getLogger().warning("Could not find locale string: " + key);
}
return '!' + key + '!';
}
}
}
private static String getString(String key, ResourceBundle bundle, Object... messageArguments) throws MissingResourceException {
return formatString(bundle.getString(key), messageArguments);
}
public static String formatString(String string, Object... messageArguments) {
if (messageArguments != null) {
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(string.replace("'", "''"));
string = formatter.format(messageArguments);
}
string = addColors(string);
return string;
}
public static Locale getCurrentLocale() {
if (bundle == null) {
initialize();
}
return bundle.getLocale();
}
private static void initialize() {
if (bundle == null) {
Locale.setDefault(new Locale("en", "US"));
Locale locale = null;
String[] myLocale = Config.getInstance().getLocale().split("[-_ ]");
if (myLocale.length == 1) {
locale = new Locale(myLocale[0]);
}
else if (myLocale.length >= 2) {
locale = new Locale(myLocale[0], myLocale[1]);
}
bundle = ResourceBundle.getBundle(BUNDLE_ROOT, locale);
enBundle = ResourceBundle.getBundle(BUNDLE_ROOT, Locale.US);
}
}
private static String addColors(String input) {
input = input.replaceAll("\\Q[[BLACK]]\\E", ChatColor.BLACK.toString());
input = input.replaceAll("\\Q[[DARK_BLUE]]\\E", ChatColor.DARK_BLUE.toString());
input = input.replaceAll("\\Q[[DARK_GREEN]]\\E", ChatColor.DARK_GREEN.toString());
input = input.replaceAll("\\Q[[DARK_AQUA]]\\E", ChatColor.DARK_AQUA.toString());
input = input.replaceAll("\\Q[[DARK_RED]]\\E", ChatColor.DARK_RED.toString());
input = input.replaceAll("\\Q[[DARK_PURPLE]]\\E", ChatColor.DARK_PURPLE.toString());
input = input.replaceAll("\\Q[[GOLD]]\\E", ChatColor.GOLD.toString());
input = input.replaceAll("\\Q[[GRAY]]\\E", ChatColor.GRAY.toString());
input = input.replaceAll("\\Q[[DARK_GRAY]]\\E", ChatColor.DARK_GRAY.toString());
input = input.replaceAll("\\Q[[BLUE]]\\E", ChatColor.BLUE.toString());
input = input.replaceAll("\\Q[[GREEN]]\\E", ChatColor.GREEN.toString());
input = input.replaceAll("\\Q[[AQUA]]\\E", ChatColor.AQUA.toString());
input = input.replaceAll("\\Q[[RED]]\\E", ChatColor.RED.toString());
input = input.replaceAll("\\Q[[LIGHT_PURPLE]]\\E", ChatColor.LIGHT_PURPLE.toString());
input = input.replaceAll("\\Q[[YELLOW]]\\E", ChatColor.YELLOW.toString());
input = input.replaceAll("\\Q[[WHITE]]\\E", ChatColor.WHITE.toString());
input = input.replaceAll("\\Q[[BOLD]]\\E", ChatColor.BOLD.toString());
input = input.replaceAll("\\Q[[UNDERLINE]]\\E", ChatColor.UNDERLINE.toString());
input = input.replaceAll("\\Q[[ITALIC]]\\E", ChatColor.ITALIC.toString());
input = input.replaceAll("\\Q[[STRIKE]]\\E", ChatColor.STRIKETHROUGH.toString());
input = input.replaceAll("\\Q[[MAGIC]]\\E", ChatColor.MAGIC.toString());
input = input.replaceAll("\\Q[[RESET]]\\E", ChatColor.RESET.toString());
input = input.replaceAll("\\Q&0\\E", ChatColor.BLACK.toString());
input = input.replaceAll("\\Q&1\\E", ChatColor.DARK_BLUE.toString());
input = input.replaceAll("\\Q&2\\E", ChatColor.DARK_GREEN.toString());
input = input.replaceAll("\\Q&3\\E", ChatColor.DARK_AQUA.toString());
input = input.replaceAll("\\Q&4\\E", ChatColor.DARK_RED.toString());
input = input.replaceAll("\\Q&5\\E", ChatColor.DARK_PURPLE.toString());
input = input.replaceAll("\\Q&6\\E", ChatColor.GOLD.toString());
input = input.replaceAll("\\Q&7\\E", ChatColor.GRAY.toString());
input = input.replaceAll("\\Q&8\\E", ChatColor.DARK_GRAY.toString());
input = input.replaceAll("\\Q&9\\E", ChatColor.BLUE.toString());
input = input.replaceAll("\\Q&a\\E", ChatColor.GREEN.toString());
input = input.replaceAll("\\Q&b\\E", ChatColor.AQUA.toString());
input = input.replaceAll("\\Q&c\\E", ChatColor.RED.toString());
input = input.replaceAll("\\Q&d\\E", ChatColor.LIGHT_PURPLE.toString());
input = input.replaceAll("\\Q&e\\E", ChatColor.YELLOW.toString());
input = input.replaceAll("\\Q&f\\E", ChatColor.WHITE.toString());
input = input.replaceAll("\\Q&l\\E", ChatColor.BOLD.toString());
input = input.replaceAll("\\Q&n\\E", ChatColor.UNDERLINE.toString());
input = input.replaceAll("\\Q&o\\E", ChatColor.ITALIC.toString());
input = input.replaceAll("\\Q&m\\E", ChatColor.STRIKETHROUGH.toString());
input = input.replaceAll("\\Q&?\\E", ChatColor.MAGIC.toString());
input = input.replaceAll("\\Q&r\\E", ChatColor.RESET.toString());
return input;
}
}

View File

@ -0,0 +1,801 @@
package com.gmail.nossr50.core.party;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.chat.ChatMode;
import com.gmail.nossr50.core.datatypes.database.UpgradeType;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.party.ItemShareType;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.core.datatypes.party.PartyLeader;
import com.gmail.nossr50.core.datatypes.party.ShareMode;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
import com.gmail.nossr50.events.party.McMMOPartyAllianceChangeEvent;
import com.gmail.nossr50.events.party.McMMOPartyChangeEvent;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.core.util.Misc;
import com.gmail.nossr50.core.util.Permissions;
import com.gmail.nossr50.core.util.player.NotificationManager;
import com.gmail.nossr50.core.data.UserManager;
import com.gmail.nossr50.core.util.sounds.SoundManager;
import com.gmail.nossr50.core.util.sounds.SoundType;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;
public final class PartyManager {
private static String partiesFilePath = mcMMO.getFlatFileDirectory() + "parties.yml";
private static List<Party> parties = new ArrayList<Party>();
private static File partyFile = new File(partiesFilePath);
private PartyManager() {}
/**
* Check if a party with a given name already exists.
*
* @param player The player to notify
* @param partyName The name of the party to check
* @return true if a party with that name exists, false otherwise
*/
public static boolean checkPartyExistence(Player player, String partyName) {
if (getParty(partyName) == null) {
return false;
}
player.sendMessage(LocaleLoader.getString("Commands.Party.AlreadyExists", partyName));
return true;
}
/**
* Checks if the player can join a party, parties can have a size limit, although there is a permission to bypass this
* @param player player who is attempting to join the party
* @param targetParty the target party
* @return true if party is full and cannot be joined
*/
public static boolean isPartyFull(Player player, Party targetParty)
{
return !Permissions.partySizeBypass(player) && Config.getInstance().getPartyMaxSize() >= 1 && targetParty.getOnlineMembers().size() >= Config.getInstance().getPartyMaxSize();
}
/**
* Attempt to change parties or join a new party.
*
* @param mcMMOPlayer The player changing or joining parties
* @param newPartyName The name of the party being joined
* @return true if the party was joined successfully, false otherwise
*/
public static boolean changeOrJoinParty(McMMOPlayer mcMMOPlayer, String newPartyName) {
Player player = mcMMOPlayer.getPlayer();
if (mcMMOPlayer.inParty()) {
Party oldParty = mcMMOPlayer.getParty();
if (!handlePartyChangeEvent(player, oldParty.getName(), newPartyName, McMMOPartyChangeEvent.EventReason.CHANGED_PARTIES)) {
return false;
}
removeFromParty(mcMMOPlayer);
}
else return handlePartyChangeEvent(player, null, newPartyName, McMMOPartyChangeEvent.EventReason.JOINED_PARTY);
return true;
}
/**
* Check if two online players are in the same party.
*
* @param firstPlayer The first player
* @param secondPlayer The second player
* @return true if they are in the same party, false otherwise
*/
public static boolean inSameParty(Player firstPlayer, Player secondPlayer) {
Party firstParty = UserManager.getPlayer(firstPlayer).getParty();
Party secondParty = UserManager.getPlayer(secondPlayer).getParty();
if (firstParty == null || secondParty == null) {
return false;
}
return firstParty.equals(secondParty);
}
public static boolean areAllies(Player firstPlayer, Player secondPlayer) {
Party firstParty = UserManager.getPlayer(firstPlayer).getParty();
Party secondParty = UserManager.getPlayer(secondPlayer).getParty();
if (firstParty == null || secondParty == null || firstParty.getAlly() == null || secondParty.getAlly() == null) {
return false;
}
return firstParty.equals(secondParty.getAlly()) && secondParty.equals(firstParty.getAlly());
}
/**
* Get the near party members.
*
* @param mcMMOPlayer The player to check
* @return the near party members
*/
public static List<Player> getNearMembers(McMMOPlayer mcMMOPlayer) {
List<Player> nearMembers = new ArrayList<Player>();
Party party = mcMMOPlayer.getParty();
if (party != null) {
Player player = mcMMOPlayer.getPlayer();
double range = Config.getInstance().getPartyShareRange();
for (Player member : party.getOnlineMembers()) {
if (!player.equals(member) && member.isValid() && Misc.isNear(player.getLocation(), member.getLocation(), range)) {
nearMembers.add(member);
}
}
}
return nearMembers;
}
public static List<Player> getNearVisibleMembers(McMMOPlayer mcMMOPlayer) {
List<Player> nearMembers = new ArrayList<Player>();
Party party = mcMMOPlayer.getParty();
if (party != null) {
Player player = mcMMOPlayer.getPlayer();
double range = Config.getInstance().getPartyShareRange();
for (Player member : party.getVisibleMembers(player)) {
if (!player.equals(member)
&& member.isValid()
&& Misc.isNear(player.getLocation(), member.getLocation(), range)) {
nearMembers.add(member);
}
}
}
return nearMembers;
}
/**
* Get a list of all players in this player's party.
*
* @param player The player to check
* @return all the players in the player's party
*/
public static LinkedHashMap<UUID, String> getAllMembers(Player player) {
Party party = getParty(player);
return party == null ? new LinkedHashMap<UUID, String>() : party.getMembers();
}
/**
* Get a list of all online players in this party.
*
* @param partyName The party to check
* @return all online players in this party
*/
public static List<Player> getOnlineMembers(String partyName) {
return getOnlineMembers(getParty(partyName));
}
/**
* Get a list of all online players in this party.
*
* @param player The player to check
* @return all online players in this party
*/
public static List<Player> getOnlineMembers(Player player) {
return getOnlineMembers(getParty(player));
}
private static List<Player> getOnlineMembers(Party party) {
return party == null ? new ArrayList<Player>() : party.getOnlineMembers();
}
/**
* Retrieve a party by its name
*
* @param partyName The party name
* @return the existing party, null otherwise
*/
public static Party getParty(String partyName) {
for (Party party : parties) {
if (party.getName().equalsIgnoreCase(partyName)) {
return party;
}
}
return null;
}
/**
* Retrieve a party by a members name
*
* @param playerName The members name
* @return the existing party, null otherwise
*/
@Deprecated
public static Party getPlayerParty(String playerName) {
for (Party party : parties) {
if (party.getMembers().keySet().contains(playerName)) {
return party;
}
}
return null;
}
/**
* Retrieve a party by a members uuid
*
* @param uuid The members uuid
* @return the existing party, null otherwise
*/
public static Party getPlayerParty(String playerName, UUID uuid) {
for (Party party : parties) {
LinkedHashMap<UUID, String> members = party.getMembers();
if (members.keySet().contains(uuid) || members.values().contains(playerName)) {
// Name changes
if (members.get(uuid) == null || !members.get(uuid).equals(playerName)) {
members.put(uuid, playerName);
}
return party;
}
}
return null;
}
/**
* Retrieve a party by member
*
* @param player The member
* @return the existing party, null otherwise
*/
public static Party getParty(Player player) {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
return mcMMOPlayer.getParty();
}
/**
* Get a list of all current parties.
*
* @return the list of parties.
*/
public static List<Party> getParties() {
return parties;
}
/**
* Remove a player from a party.
*
* @param player The player to remove
* @param party The party
*/
public static void removeFromParty(OfflinePlayer player, Party party) {
LinkedHashMap<UUID, String> members = party.getMembers();
String playerName = player.getName();
members.remove(player.getUniqueId());
if (player.isOnline()) {
party.getOnlineMembers().remove(player.getPlayer());
}
if (members.isEmpty()) {
parties.remove(party);
}
else {
// If the leaving player was the party leader, appoint a new leader from the party members
if (party.getLeader().getUniqueId().equals(player.getUniqueId())) {
setPartyLeader(members.keySet().iterator().next(), party);
}
informPartyMembersQuit(party, playerName);
}
}
/**
* Remove a player from a party.
*
* @param mcMMOPlayer The player to remove
*/
public static void removeFromParty(McMMOPlayer mcMMOPlayer) {
removeFromParty(mcMMOPlayer.getPlayer(), mcMMOPlayer.getParty());
processPartyLeaving(mcMMOPlayer);
}
/**
* Disband a party. Kicks out all members and removes the party.
*
* @param party The party to remove
*/
public static void disbandParty(Party party) {
for (Player member : party.getOnlineMembers()) {
processPartyLeaving(UserManager.getPlayer(member));
}
// Disband the alliance between the disbanded party and it's ally
if (party.getAlly() != null) {
party.getAlly().setAlly(null);
}
parties.remove(party);
}
/**
* Create a new party
*
* @param mcMMOPlayer The player to add to the party
* @param partyName The party to add the player to
* @param password The password for this party, null if there was no password
*/
public static void createParty(McMMOPlayer mcMMOPlayer, String partyName, String password) {
Player player = mcMMOPlayer.getPlayer();
Party party = new Party(new PartyLeader(player.getUniqueId(), player.getName()), partyName.replace(".", ""), password);
if (password != null) {
player.sendMessage(LocaleLoader.getString("Party.Password.Set", password));
}
parties.add(party);
player.sendMessage(LocaleLoader.getString("Commands.Party.Create", party.getName()));
addToParty(mcMMOPlayer, party);
}
/**
* Check if a player can join a party
*
* @param player The player trying to join a party
* @param party The party
* @param password The password provided by the player
* @return true if the player can join the party
*/
public static boolean checkPartyPassword(Player player, Party party, String password) {
if (party.isLocked()) {
String partyPassword = party.getPassword();
if (partyPassword == null) {
player.sendMessage(LocaleLoader.getString("Party.Locked"));
return false;
}
if (password == null) {
player.sendMessage(LocaleLoader.getString("Party.Password.None"));
return false;
}
if (!password.equals(partyPassword)) {
player.sendMessage(LocaleLoader.getString("Party.Password.Incorrect"));
return false;
}
}
return true;
}
/**
* Accept a party invitation
*
* @param mcMMOPlayer The player to add to the party
*/
public static void joinInvitedParty(McMMOPlayer mcMMOPlayer) {
Party invite = mcMMOPlayer.getPartyInvite();
// Check if the party still exists, it might have been disbanded
if (!parties.contains(invite)) {
NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.PARTY_MESSAGE, "Party.Disband");
return;
}
/*
* Don't let players join a full party
*/
if(Config.getInstance().getPartyMaxSize() > 0 && invite.getMembers().size() >= Config.getInstance().getPartyMaxSize())
{
NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.PARTY_MESSAGE, "Commands.Party.PartyFull.InviteAccept", invite.getName(), String.valueOf(Config.getInstance().getPartyMaxSize()));
return;
}
NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.PARTY_MESSAGE, "Commands.Party.Invite.Accepted", invite.getName());
mcMMOPlayer.removePartyInvite();
addToParty(mcMMOPlayer, invite);
}
/**
* Accept a party alliance invitation
*
* @param mcMMOPlayer The player who accepts the alliance invite
*/
public static void acceptAllianceInvite(McMMOPlayer mcMMOPlayer) {
Party invite = mcMMOPlayer.getPartyAllianceInvite();
Player player = mcMMOPlayer.getPlayer();
// Check if the party still exists, it might have been disbanded
if (!parties.contains(invite)) {
player.sendMessage(LocaleLoader.getString("Party.Disband"));
return;
}
if (!handlePartyChangeAllianceEvent(player, mcMMOPlayer.getParty().getName(), invite.getName(), McMMOPartyAllianceChangeEvent.EventReason.FORMED_ALLIANCE)) {
return;
}
player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Invite.Accepted", invite.getName()));
mcMMOPlayer.removePartyAllianceInvite();
createAlliance(mcMMOPlayer.getParty(), invite);
}
public static void createAlliance(Party firstParty, Party secondParty) {
firstParty.setAlly(secondParty);
secondParty.setAlly(firstParty);
for (Player member : firstParty.getOnlineMembers()) {
member.sendMessage(LocaleLoader.getString("Party.Alliance.Formed", secondParty.getName()));
}
for (Player member : secondParty.getOnlineMembers()) {
member.sendMessage(LocaleLoader.getString("Party.Alliance.Formed", firstParty.getName()));
}
}
public static boolean disbandAlliance(Player player, Party firstParty, Party secondParty){
if (!handlePartyChangeAllianceEvent(player, firstParty.getName(), secondParty.getName(), McMMOPartyAllianceChangeEvent.EventReason.DISBAND_ALLIANCE)) {
return false;
}
PartyManager.disbandAlliance(firstParty, secondParty);
return true;
}
private static void disbandAlliance(Party firstParty, Party secondParty) {
firstParty.setAlly(null);
secondParty.setAlly(null);
for (Player member : firstParty.getOnlineMembers()) {
member.sendMessage(LocaleLoader.getString("Party.Alliance.Disband", secondParty.getName()));
}
for (Player member : secondParty.getOnlineMembers()) {
member.sendMessage(LocaleLoader.getString("Party.Alliance.Disband", firstParty.getName()));
}
}
/**
* Add a player to a party
*
* @param mcMMOPlayer The player to add to the party
* @param party The party
*/
public static void addToParty(McMMOPlayer mcMMOPlayer, Party party) {
Player player = mcMMOPlayer.getPlayer();
String playerName = player.getName();
informPartyMembersJoin(party, playerName);
mcMMOPlayer.setParty(party);
party.getMembers().put(player.getUniqueId(), player.getName());
party.getOnlineMembers().add(player);
}
/**
* Get the leader of a party.
*
* @param partyName The party name
* @return the leader of the party
*/
public static String getPartyLeaderName(String partyName) {
Party party = getParty(partyName);
return party == null ? null : party.getLeader().getPlayerName();
}
/**
* Set the leader of a party.
*
* @param uuid The uuid of the player to set as leader
* @param party The party
*/
public static void setPartyLeader(UUID uuid, Party party) {
OfflinePlayer player = mcMMO.p.getServer().getOfflinePlayer(uuid);
UUID leaderUniqueId = party.getLeader().getUniqueId();
for (Player member : party.getOnlineMembers()) {
UUID memberUniqueId = member.getUniqueId();
if (memberUniqueId.equals(player.getUniqueId())) {
member.sendMessage(LocaleLoader.getString("Party.Owner.Player"));
}
else if (memberUniqueId.equals(leaderUniqueId)) {
member.sendMessage(LocaleLoader.getString("Party.Owner.NotLeader"));
}
else {
member.sendMessage(LocaleLoader.getString("Party.Owner.New", player.getName()));
}
}
party.setLeader(new PartyLeader(player.getUniqueId(), player.getName()));
}
/**
* Check if a player can invite others to his party.
*
* @return true if the player can invite
*/
public static boolean canInvite(McMMOPlayer mcMMOPlayer) {
Party party = mcMMOPlayer.getParty();
return !party.isLocked() || party.getLeader().getUniqueId().equals(mcMMOPlayer.getPlayer().getUniqueId());
}
/**
* Load party file.
*/
public static void loadParties() {
if (!partyFile.exists()) {
return;
}
if (mcMMO.getUpgradeManager().shouldUpgrade(UpgradeType.ADD_UUIDS_PARTY)) {
loadAndUpgradeParties();
return;
}
YamlConfiguration partiesFile = YamlConfiguration.loadConfiguration(partyFile);
ArrayList<Party> hasAlly = new ArrayList<Party>();
for (String partyName : partiesFile.getConfigurationSection("").getKeys(false)) {
Party party = new Party(partyName);
String[] leaderSplit = partiesFile.getString(partyName + ".Leader").split("[|]");
party.setLeader(new PartyLeader(UUID.fromString(leaderSplit[0]), leaderSplit[1]));
party.setPassword(partiesFile.getString(partyName + ".Password"));
party.setLocked(partiesFile.getBoolean(partyName + ".Locked"));
party.setLevel(partiesFile.getInt(partyName + ".Level"));
party.setXp(partiesFile.getInt(partyName + ".Xp"));
if (partiesFile.getString(partyName + ".Ally") != null) {
hasAlly.add(party);
}
party.setXpShareMode(ShareMode.getShareMode(partiesFile.getString(partyName + ".ExpShareMode", "NONE")));
party.setItemShareMode(ShareMode.getShareMode(partiesFile.getString(partyName + ".ItemShareMode", "NONE")));
for (ItemShareType itemShareType : ItemShareType.values()) {
party.setSharingDrops(itemShareType, partiesFile.getBoolean(partyName + ".ItemShareType." + itemShareType.toString(), true));
}
LinkedHashMap<UUID, String> members = party.getMembers();
for (String memberEntry : partiesFile.getStringList(partyName + ".Members")) {
String[] memberSplit = memberEntry.split("[|]");
members.put(UUID.fromString(memberSplit[0]), memberSplit[1]);
}
parties.add(party);
}
mcMMO.p.debug("Loaded (" + parties.size() + ") Parties...");
for (Party party : hasAlly) {
party.setAlly(PartyManager.getParty(partiesFile.getString(party.getName() + ".Ally")));
}
}
/**
* Save party file.
*/
public static void saveParties() {
if (partyFile.exists()) {
if (!partyFile.delete()) {
mcMMO.p.getLogger().warning("Could not delete party file. Party saving failed!");
return;
}
}
YamlConfiguration partiesFile = new YamlConfiguration();
mcMMO.p.debug("Saving Parties... (" + parties.size() + ")");
for (Party party : parties) {
String partyName = party.getName();
PartyLeader leader = party.getLeader();
partiesFile.set(partyName + ".Leader", leader.getUniqueId().toString() + "|" + leader.getPlayerName());
partiesFile.set(partyName + ".Password", party.getPassword());
partiesFile.set(partyName + ".Locked", party.isLocked());
partiesFile.set(partyName + ".Level", party.getLevel());
partiesFile.set(partyName + ".Xp", (int) party.getXp());
partiesFile.set(partyName + ".Ally", (party.getAlly() != null) ? party.getAlly().getName() : "");
partiesFile.set(partyName + ".ExpShareMode", party.getXpShareMode().toString());
partiesFile.set(partyName + ".ItemShareMode", party.getItemShareMode().toString());
for (ItemShareType itemShareType : ItemShareType.values()) {
partiesFile.set(partyName + ".ItemShareType." + itemShareType.toString(), party.sharingDrops(itemShareType));
}
List<String> members = new ArrayList<String>();
for (Entry<UUID, String> memberEntry : party.getMembers().entrySet()) {
String memberUniqueId = memberEntry.getKey() == null ? "" : memberEntry.getKey().toString();
String memberName = memberEntry.getValue();
if (!members.contains(memberName)) {
members.add(memberUniqueId + "|" + memberName);
}
}
partiesFile.set(partyName + ".Members", members);
}
try {
partiesFile.save(partyFile);
}
catch (Exception e) {
e.printStackTrace();
}
}
private static void loadAndUpgradeParties() {
YamlConfiguration partiesFile = YamlConfiguration.loadConfiguration(partyFile);
if (!partyFile.renameTo(new File(mcMMO.getFlatFileDirectory() + "parties.yml.converted"))) {
mcMMO.p.getLogger().severe("Could not rename parties.yml to parties.yml.converted!");
return;
}
ArrayList<Party> hasAlly = new ArrayList<Party>();
for (String partyName : partiesFile.getConfigurationSection("").getKeys(false)) {
Party party = new Party(partyName);
String leaderName = partiesFile.getString(partyName + ".Leader");
PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(leaderName, false);
if (!profile.isLoaded()) {
mcMMO.p.getLogger().warning("Could not find UUID in database for party leader " + leaderName + " in party " + partyName);
continue;
}
UUID leaderUniqueId = profile.getUniqueId();
party.setLeader(new PartyLeader(leaderUniqueId, leaderName));
party.setPassword(partiesFile.getString(partyName + ".Password"));
party.setLocked(partiesFile.getBoolean(partyName + ".Locked"));
party.setLevel(partiesFile.getInt(partyName + ".Level"));
party.setXp(partiesFile.getInt(partyName + ".Xp"));
if (partiesFile.getString(partyName + ".Ally") != null) {
hasAlly.add(party);
}
party.setXpShareMode(ShareMode.getShareMode(partiesFile.getString(partyName + ".ExpShareMode", "NONE")));
party.setItemShareMode(ShareMode.getShareMode(partiesFile.getString(partyName + ".ItemShareMode", "NONE")));
for (ItemShareType itemShareType : ItemShareType.values()) {
party.setSharingDrops(itemShareType, partiesFile.getBoolean(partyName + ".ItemShareType." + itemShareType.toString(), true));
}
LinkedHashMap<UUID, String> members = party.getMembers();
for (String memberName : partiesFile.getStringList(partyName + ".Members")) {
PlayerProfile memberProfile = mcMMO.getDatabaseManager().loadPlayerProfile(memberName, false);
if (!memberProfile.isLoaded()) {
mcMMO.p.getLogger().warning("Could not find UUID in database for party member " + memberName + " in party " + partyName);
continue;
}
UUID memberUniqueId = memberProfile.getUniqueId();
members.put(memberUniqueId, memberName);
}
parties.add(party);
}
mcMMO.p.debug("Loaded (" + parties.size() + ") Parties...");
for (Party party : hasAlly) {
party.setAlly(PartyManager.getParty(partiesFile.getString(party.getName() + ".Ally")));
}
mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_UUIDS_PARTY);
}
/**
* Handle party change event.
*
* @param player The player changing parties
* @param oldPartyName The name of the old party
* @param newPartyName The name of the new party
* @param reason The reason for changing parties
* @return true if the change event was successful, false otherwise
*/
public static boolean handlePartyChangeEvent(Player player, String oldPartyName, String newPartyName, McMMOPartyChangeEvent.EventReason reason) {
McMMOPartyChangeEvent event = new McMMOPartyChangeEvent(player, oldPartyName, newPartyName, reason);
mcMMO.p.getServer().getPluginManager().callEvent(event);
return !event.isCancelled();
}
/**
* Handle party alliance change event.
*
* @param player The player changing party alliances
* @param oldAllyName The name of the old ally
* @param newAllyName The name of the new ally
* @param reason The reason for changing allies
* @return true if the change event was successful, false otherwise
*/
public static boolean handlePartyChangeAllianceEvent(Player player, String oldAllyName, String newAllyName, McMMOPartyAllianceChangeEvent.EventReason reason) {
McMMOPartyAllianceChangeEvent event = new McMMOPartyAllianceChangeEvent(player, oldAllyName, newAllyName, reason);
mcMMO.p.getServer().getPluginManager().callEvent(event);
return !event.isCancelled();
}
/**
* Remove party data from the mcMMOPlayer.
*
* @param mcMMOPlayer The player to remove party data from.
*/
public static void processPartyLeaving(McMMOPlayer mcMMOPlayer) {
mcMMOPlayer.removeParty();
mcMMOPlayer.disableChat(ChatMode.PARTY);
mcMMOPlayer.setItemShareModifier(10);
}
/**
* Notify party members when the party levels up.
*
* @param party The concerned party
* @param levelsGained The amount of levels gained
* @param level The current party level
*/
public static void informPartyMembersLevelUp(Party party, int levelsGained, int level) {
boolean levelUpSoundsEnabled = Config.getInstance().getLevelUpSoundsEnabled();
for (Player member : party.getOnlineMembers()) {
member.sendMessage(LocaleLoader.getString("Party.LevelUp", levelsGained, level));
if (levelUpSoundsEnabled) {
SoundManager.sendSound(member, member.getLocation(), SoundType.LEVEL_UP);
}
}
}
/**
* Notify party members when a player joins.
*
* @param party The concerned party
* @param playerName The name of the player that joined
*/
private static void informPartyMembersJoin(Party party, String playerName) {
for (Player member : party.getOnlineMembers()) {
member.sendMessage(LocaleLoader.getString("Party.InformedOnJoin", playerName));
}
}
/**
* Notify party members when a party member quits.
*
* @param party The concerned party
* @param playerName The name of the player that left
*/
private static void informPartyMembersQuit(Party party, String playerName) {
for (Player member : party.getOnlineMembers()) {
member.sendMessage(LocaleLoader.getString("Party.InformedOnQuit", playerName));
}
}
}

View File

@ -0,0 +1,165 @@
package com.gmail.nossr50.core.party;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.config.party.ItemWeightConfig;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
import com.gmail.nossr50.core.datatypes.party.ItemShareType;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.core.datatypes.party.ShareMode;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.util.Misc;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public final class ShareHandler {
private ShareHandler() {}
/**
* Distribute Xp amongst party members.
*
* @param xp Xp without party sharing
* @param mcMMOPlayer Player initiating the Xp gain
* @param primarySkillType Skill being used
* @return True is the xp has been shared
*/
public static boolean handleXpShare(float xp, McMMOPlayer mcMMOPlayer, PrimarySkillType primarySkillType, XPGainReason xpGainReason) {
Party party = mcMMOPlayer.getParty();
if (party.getXpShareMode() != ShareMode.EQUAL) {
return false;
}
List<Player> nearMembers = PartyManager.getNearVisibleMembers(mcMMOPlayer);
if (nearMembers.isEmpty()) {
return false;
}
nearMembers.add(mcMMOPlayer.getPlayer());
int partySize = nearMembers.size();
double shareBonus = Math.min(Config.getInstance().getPartyShareBonusBase() + (partySize * Config.getInstance().getPartyShareBonusIncrease()), Config.getInstance().getPartyShareBonusCap());
float splitXp = (float) (xp / partySize * shareBonus);
for (Player member : nearMembers) {
UserManager.getPlayer(member).beginUnsharedXpGain(primarySkillType, splitXp, xpGainReason, XPGainSource.PARTY_MEMBERS);
}
return true;
}
/**
* Distribute Items amongst party members.
*
* @param drop Item that will get shared
* @param mcMMOPlayer Player who picked up the item
* @return True if the item has been shared
*/
public static boolean handleItemShare(Item drop, McMMOPlayer mcMMOPlayer) {
ItemStack itemStack = drop.getItemStack();
ItemShareType dropType = ItemShareType.getShareType(itemStack);
if (dropType == null) {
return false;
}
Party party = mcMMOPlayer.getParty();
if (!party.sharingDrops(dropType)) {
return false;
}
ShareMode shareMode = party.getItemShareMode();
if (shareMode == ShareMode.NONE) {
return false;
}
List<Player> nearMembers = PartyManager.getNearMembers(mcMMOPlayer);
if (nearMembers.isEmpty()) {
return false;
}
Player winningPlayer = null;
ItemStack newStack = itemStack.clone();
nearMembers.add(mcMMOPlayer.getPlayer());
int partySize = nearMembers.size();
drop.remove();
newStack.setAmount(1);
switch (shareMode) {
case EQUAL:
int itemWeight = ItemWeightConfig.getInstance().getItemWeight(itemStack.getType());
for (int i = 0; i < itemStack.getAmount(); i++) {
int highestRoll = 0;
for (Player member : nearMembers) {
McMMOPlayer mcMMOMember = UserManager.getPlayer(member);
int itemShareModifier = mcMMOMember.getItemShareModifier();
int diceRoll = Misc.getRandom().nextInt(itemShareModifier);
if (diceRoll <= highestRoll) {
mcMMOMember.setItemShareModifier(itemShareModifier + itemWeight);
continue;
}
highestRoll = diceRoll;
if (winningPlayer != null) {
McMMOPlayer mcMMOWinning = UserManager.getPlayer(winningPlayer);
mcMMOWinning.setItemShareModifier(mcMMOWinning.getItemShareModifier() + itemWeight);
}
winningPlayer = member;
}
McMMOPlayer mcMMOTarget = UserManager.getPlayer(winningPlayer);
mcMMOTarget.setItemShareModifier(mcMMOTarget.getItemShareModifier() - itemWeight);
awardDrop(winningPlayer, newStack);
}
return true;
case RANDOM:
for (int i = 0; i < itemStack.getAmount(); i++) {
winningPlayer = nearMembers.get(Misc.getRandom().nextInt(partySize));
awardDrop(winningPlayer, newStack);
}
return true;
default:
return false;
}
}
public static XPGainReason getSharedXpGainReason(XPGainReason xpGainReason) {
if (xpGainReason == XPGainReason.PVE) {
return XPGainReason.SHARED_PVE;
}
else if (xpGainReason == XPGainReason.PVP) {
return XPGainReason.SHARED_PVP;
}
else {
return xpGainReason;
}
}
private static void awardDrop(Player winningPlayer, ItemStack drop) {
if (winningPlayer.getInventory().addItem(drop).size() != 0) {
winningPlayer.getWorld().dropItem(winningPlayer.getLocation(), drop);
}
winningPlayer.updateInventory();
}
}

View File

@ -0,0 +1,23 @@
package com.gmail.nossr50.core.runnables;
import com.gmail.nossr50.core.runnables.skills.AprilTask;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import org.bukkit.scheduler.BukkitRunnable;
public class CheckDateTask extends BukkitRunnable {
@Override
public void run() {
if (!mcMMO.getHolidayManager().isAprilFirst()) {
return;
}
// Set up jokes
new AprilTask().runTaskTimer(mcMMO.p, 1L * 60L * Misc.TICK_CONVERSION_FACTOR, 10L * 60L * Misc.TICK_CONVERSION_FACTOR);
mcMMO.getHolidayManager().registerAprilCommand();
// Jokes deployed.
this.cancel();
}
}

View File

@ -0,0 +1,29 @@
package com.gmail.nossr50.core.runnables;
import com.gmail.nossr50.mcMMO;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
public class MobHealthDisplayUpdaterTask extends BukkitRunnable {
private LivingEntity target;
private String oldName;
private boolean oldNameVisible;
public MobHealthDisplayUpdaterTask(LivingEntity target) {
if (target.isValid()) {
this.target = target;
this.oldName = target.getMetadata(mcMMO.customNameKey).get(0).asString();
this.oldNameVisible = target.getMetadata(mcMMO.customVisibleKey).get(0).asBoolean();
}
}
@Override
public void run() {
if (target != null && target.isValid()) {
target.setCustomNameVisible(oldNameVisible);
target.setCustomName(oldName);
target.removeMetadata(mcMMO.customNameKey, mcMMO.p);
target.removeMetadata(mcMMO.customVisibleKey, mcMMO.p);
}
}
}

View File

@ -0,0 +1,46 @@
package com.gmail.nossr50.core.runnables;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.BlockUtils;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
public class PistonTrackerTask extends BukkitRunnable {
private List<Block> blocks;
private BlockFace direction;
private Block futureEmptyBlock;
public PistonTrackerTask(List<Block> blocks, BlockFace direction, Block futureEmptyBlock) {
this.blocks = blocks;
this.direction = direction;
this.futureEmptyBlock = futureEmptyBlock;
}
@Override
public void run() {
// Check to see if futureEmptyBlock is empty - if it isn't; the blocks didn't move
if (!BlockUtils.isPistonPiece(futureEmptyBlock.getState())) {
return;
}
if (mcMMO.getPlaceStore().isTrue(futureEmptyBlock)) {
mcMMO.getPlaceStore().setFalse(futureEmptyBlock);
}
for (Block b : blocks) {
Block nextBlock = b.getRelative(direction);
if (nextBlock.hasMetadata(mcMMO.blockMetadataKey)) {
mcMMO.getPlaceStore().setTrue(nextBlock);
nextBlock.removeMetadata(mcMMO.blockMetadataKey, mcMMO.p);
}
else if (mcMMO.getPlaceStore().isTrue(nextBlock)) {
// Block doesn't have metadatakey but isTrue - set it to false
mcMMO.getPlaceStore().setFalse(nextBlock);
}
}
}
}

View File

@ -0,0 +1,23 @@
package com.gmail.nossr50.core.runnables;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.runnables.player.PlayerProfileSaveTask;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.scheduler.BukkitRunnable;
public class SaveTimerTask extends BukkitRunnable {
@Override
public void run() {
// All player data will be saved periodically through this
int count = 1;
for (McMMOPlayer mcMMOPlayer : UserManager.getPlayers()) {
new PlayerProfileSaveTask(mcMMOPlayer.getProfile()).runTaskLaterAsynchronously(mcMMO.p, count);
count++;
}
PartyManager.saveParties();
}
}

View File

@ -0,0 +1,35 @@
package com.gmail.nossr50.core.runnables;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.BlockUtils;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.scheduler.BukkitRunnable;
public class StickyPistonTrackerTask extends BukkitRunnable {
private BlockFace direction;
private Block block;
private Block movedBlock;
public StickyPistonTrackerTask(BlockFace direction, Block block, Block movedBlock) {
this.direction = direction;
this.block = block;
this.movedBlock = movedBlock;
}
@Override
public void run() {
if (!mcMMO.getPlaceStore().isTrue(movedBlock.getRelative(direction))) {
return;
}
if (!BlockUtils.isPistonPiece(movedBlock.getState())) {
// The block didn't move
return;
}
// The sticky piston actually pulled the block so move the PlaceStore data
mcMMO.getPlaceStore().setFalse(movedBlock.getRelative(direction));
mcMMO.getPlaceStore().setTrue(movedBlock);
}
}

View File

@ -0,0 +1,128 @@
package com.gmail.nossr50.core.runnables.backups;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.mcMMO;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class CleanBackupsTask extends BukkitRunnable {
private static final String BACKUP_DIRECTORY = mcMMO.getMainDirectory() + "net.shatteredlands.shatt.backup" + File.separator;
private static final File BACKUP_DIR = new File(BACKUP_DIRECTORY);
@Override
public void run() {
List<Integer> savedDays = new ArrayList<Integer>();
HashMap<Integer, List<Integer>> savedYearsWeeks = new HashMap<Integer, List<Integer>>();
List<File> toDelete = new ArrayList<File>();
int amountTotal = 0;
int amountDeleted = 0;
if (BACKUP_DIR.listFiles() == null) {
return;
}
// Check files in net.shatteredlands.shatt.backup folder from oldest to newest
for (File file : BACKUP_DIR.listFiles()) {
if (!file.isFile() || file.isDirectory()) {
continue;
}
amountTotal++;
String fileName = file.getName();
Date date = getDate(fileName.split("[.]")[0]);
if (!fileName.contains(".zip") || date == null) {
mcMMO.p.debug("Could not determine date for file: " + fileName);
continue;
}
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
int year = cal.get(Calendar.YEAR);
if (isPast24Hours(date) && Config.getInstance().getKeepLast24Hours()) {
// Keep all files from the last 24 hours
continue;
}
else if (isLastWeek(date) && !savedDays.contains(dayOfWeek) && Config.getInstance().getKeepDailyLastWeek()) {
// Keep daily backups of the past week
savedDays.add(dayOfWeek);
continue;
}
else {
List<Integer> savedWeeks = savedYearsWeeks.get(year);
if (savedWeeks == null) {
savedWeeks = new ArrayList<Integer>();
savedYearsWeeks.put(year, savedWeeks);
}
if (!savedWeeks.contains(weekOfYear) && Config.getInstance().getKeepWeeklyPastMonth()) {
// Keep one net.shatteredlands.shatt.backup of each week
savedWeeks.add(weekOfYear);
continue;
}
}
amountDeleted++;
toDelete.add(file);
}
if (toDelete.isEmpty()) {
return;
}
mcMMO.p.getLogger().info("Cleaned net.shatteredlands.shatt.backup files. Deleted " + amountDeleted + " of " + amountTotal + " files.");
for (File file : toDelete) {
if (file.delete()) {
mcMMO.p.debug("Deleted: " + file.getName());
}
}
}
/**
* Check if date is within last 24 hours
*
* @param date date to check
*
* @return true is date is within last 24 hours, false if otherwise
*/
private boolean isPast24Hours(Date date) {
Date modifiedDate = new Date(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(24, TimeUnit.HOURS));
return date.after(modifiedDate);
}
/**
* Check if date is within the last week
*
* @param date date to check
*
* @return true is date is within the last week, false if otherwise
*/
private boolean isLastWeek(Date date) {
Date modifiedDate = new Date(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS));
return date.after(modifiedDate);
}
private Date getDate(String fileName) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
Date date;
try {
date = dateFormat.parse(fileName);
}
catch (ParseException e) {
return null;
}
return date;
}
}

View File

@ -0,0 +1,20 @@
package com.gmail.nossr50.core.runnables.commands;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class McScoreboardKeepTask extends BukkitRunnable {
private Player player;
public McScoreboardKeepTask(Player player) {
this.player = player;
}
@Override
public void run() {
if (player.isValid() && ScoreboardManager.isBoardShown(player.getName())) {
ScoreboardManager.keepBoard(player.getName());
}
}
}

View File

@ -0,0 +1,38 @@
package com.gmail.nossr50.core.runnables.commands;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import org.apache.commons.lang.Validate;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Map;
public class McrankCommandAsyncTask extends BukkitRunnable {
private final String playerName;
private final CommandSender sender;
private final boolean useBoard, useChat;
public McrankCommandAsyncTask(String playerName, CommandSender sender, boolean useBoard, boolean useChat) {
Validate.isTrue(useBoard || useChat, "Attempted to start a rank retrieval with both board and chat off");
Validate.notNull(sender, "Attempted to start a rank retrieval with no recipient");
if (useBoard) {
Validate.isTrue(sender instanceof Player, "Attempted to start a rank retrieval displaying scoreboard to a non-player");
}
this.playerName = playerName;
this.sender = sender;
this.useBoard = useBoard;
this.useChat = useChat;
}
@Override
public void run() {
Map<PrimarySkillType, Integer> skills = mcMMO.getDatabaseManager().readRank(playerName);
new McrankCommandDisplayTask(skills, sender, playerName, useBoard, useChat).runTaskLater(mcMMO.p, 1);
}
}

View File

@ -0,0 +1,71 @@
package com.gmail.nossr50.core.runnables.commands;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Map;
/**
* Display the results of McrankCommandAsyncTask to the sender.
*/
public class McrankCommandDisplayTask extends BukkitRunnable {
private final Map<PrimarySkillType, Integer> skills;
private final CommandSender sender;
private final String playerName;
private final boolean useBoard, useChat;
McrankCommandDisplayTask(Map<PrimarySkillType, Integer> skills, CommandSender sender, String playerName, boolean useBoard, boolean useChat) {
this.skills = skills;
this.sender = sender;
this.playerName = playerName;
this.useBoard = useBoard;
this.useChat = useChat;
}
@Override
public void run() {
if (useBoard && Config.getInstance().getScoreboardsEnabled()) {
displayBoard();
}
if (useChat) {
displayChat();
}
((Player) sender).removeMetadata(mcMMO.databaseCommandKey, mcMMO.p);
}
private void displayChat() {
Player player = mcMMO.p.getServer().getPlayerExact(playerName);
Integer rank;
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Heading"));
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName));
for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
if (!skill.getPermissions(player)) {
continue;
}
rank = skills.get(skill);
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", skill.getName(), (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank)));
}
rank = skills.get(null);
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Overall", (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank)));
}
public void displayBoard() {
if (sender.getName().equalsIgnoreCase(playerName)) {
ScoreboardManager.showPlayerRankScoreboard((Player) sender, skills);
}
else {
ScoreboardManager.showPlayerRankScoreboardOthers((Player) sender, playerName, skills);
}
}
}

View File

@ -0,0 +1,40 @@
package com.gmail.nossr50.core.runnables.commands;
import com.gmail.nossr50.core.datatypes.database.PlayerStat;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import org.apache.commons.lang.Validate;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
public class MctopCommandAsyncTask extends BukkitRunnable {
private final CommandSender sender;
private final PrimarySkillType skill;
private final int page;
private final boolean useBoard, useChat;
public MctopCommandAsyncTask(int page, PrimarySkillType skill, CommandSender sender, boolean useBoard, boolean useChat) {
Validate.isTrue(useBoard || useChat, "Attempted to start a rank retrieval with both board and chat off");
Validate.notNull(sender, "Attempted to start a rank retrieval with no recipient");
if (useBoard) {
Validate.isTrue(sender instanceof Player, "Attempted to start a rank retrieval displaying scoreboard to a non-player");
}
this.page = page;
this.skill = skill;
this.sender = sender;
this.useBoard = useBoard;
this.useChat = useChat;
}
@Override
public void run() {
final List<PlayerStat> userStats = mcMMO.getDatabaseManager().readLeaderboard(skill, page, 10);
new MctopCommandDisplayTask(userStats, page, skill, sender, useBoard, useChat).runTaskLater(mcMMO.p, 1);
}
}

View File

@ -0,0 +1,96 @@
package com.gmail.nossr50.core.runnables.commands;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.database.PlayerStat;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.List;
/**
* Display the results of {@link MctopCommandAsyncTask} to the sender.
*/
public class MctopCommandDisplayTask extends BukkitRunnable {
private final List<PlayerStat> userStats;
private final CommandSender sender;
private final PrimarySkillType skill;
private final int page;
private final boolean useBoard, useChat;
MctopCommandDisplayTask(List<PlayerStat> userStats, int page, PrimarySkillType skill, CommandSender sender, boolean useBoard, boolean useChat) {
this.userStats = userStats;
this.page = page;
this.skill = skill;
this.sender = sender;
this.useBoard = useBoard;
this.useChat = useChat;
}
@Override
public void run() {
if (useBoard && Config.getInstance().getScoreboardsEnabled()) {
displayBoard();
}
if (useChat) {
displayChat();
}
if (sender instanceof Player) {
((Player) sender).removeMetadata(mcMMO.databaseCommandKey, mcMMO.p);
}
if(sender instanceof Player)
sender.sendMessage(LocaleLoader.getString("Commands.mctop.Tip"));
}
private void displayChat() {
if (skill == null) {
if(sender instanceof Player) {
sender.sendMessage(LocaleLoader.getString("Commands.PowerLevel.Leaderboard"));
}
else {
sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.PowerLevel.Leaderboard")));
}
}
else {
if(sender instanceof Player) {
sender.sendMessage(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getName()));
}
else {
sender.sendMessage(ChatColor.stripColor(LocaleLoader.getString("Commands.Skill.Leaderboard", skill.getName())));
}
}
int place = (page * 10) - 9;
for (PlayerStat stat : userStats) {
// Format:
// 01. Playername - skill value
// 12. Playername - skill value
if(sender instanceof Player) {
sender.sendMessage(String.format("%2d. %s%s - %s%s", place, ChatColor.GREEN, stat.name, ChatColor.WHITE, stat.statVal));
}
else {
sender.sendMessage(String.format("%2d. %s - %s", place, stat.name, stat.statVal));
}
place++;
}
}
private void displayBoard() {
if (skill == null) {
ScoreboardManager.showTopPowerScoreboard((Player) sender, page, userStats);
}
else {
ScoreboardManager.showTopScoreboard((Player) sender, skill, page, userStats);
}
}
}

View File

@ -0,0 +1,31 @@
package com.gmail.nossr50.core.runnables.database;
import com.gmail.nossr50.core.data.database.DatabaseManager;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
public class DatabaseConversionTask extends BukkitRunnable {
private final DatabaseManager sourceDatabase;
private final CommandSender sender;
private final String message;
public DatabaseConversionTask(DatabaseManager sourceDatabase, CommandSender sender, String oldType, String newType) {
this.sourceDatabase = sourceDatabase;
this.sender = sender;
message = LocaleLoader.getString("Commands.mcconvert.Database.Finish", oldType, newType);
}
@Override
public void run() {
sourceDatabase.convertUsers(mcMMO.getDatabaseManager());
mcMMO.p.getServer().getScheduler().runTask(mcMMO.p, new Runnable() {
@Override
public void run() {
sender.sendMessage(message);
}
});
}
}

View File

@ -0,0 +1,90 @@
package com.gmail.nossr50.core.runnables.database;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.core.data.database.DatabaseManager;
import com.gmail.nossr50.core.datatypes.experience.FormulaType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
public class FormulaConversionTask extends BukkitRunnable {
private CommandSender sender;
private FormulaType formulaType;
public FormulaConversionTask(CommandSender sender, FormulaType formulaType) {
this.sender = sender;
this.formulaType = formulaType;
}
@Override
public void run() {
int convertedUsers = 0;
long startMillis = System.currentTimeMillis();
for (String playerName : mcMMO.getDatabaseManager().getStoredUsers()) {
McMMOPlayer mcMMOPlayer = UserManager.getOfflinePlayer(playerName);
PlayerProfile profile;
// If the mcMMOPlayer doesn't exist, create a temporary profile and check if it's present in the database. If it's not, abort the process.
if (mcMMOPlayer == null) {
profile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName, false);
if (!profile.isLoaded()) {
mcMMO.p.debug("Profile not loaded.");
continue;
}
editValues(profile);
// Since this is a temporary profile, we save it here.
profile.scheduleAsyncSave();
}
else {
profile = mcMMOPlayer.getProfile();
editValues(profile);
}
convertedUsers++;
Misc.printProgress(convertedUsers, DatabaseManager.progressInterval, startMillis);
}
mcMMO.getFormulaManager().setPreviousFormulaType(formulaType);
sender.sendMessage(LocaleLoader.getString("Commands.mcconvert.Experience.Finish", formulaType.toString()));
}
private void editValues(PlayerProfile profile) {
mcMMO.p.debug("========================================================================");
mcMMO.p.debug("Conversion report for " + profile.getPlayerName() + ":");
for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
int oldLevel = profile.getSkillLevel(primarySkillType);
int oldXPLevel = profile.getSkillXpLevel(primarySkillType);
int totalOldXP = mcMMO.getFormulaManager().calculateTotalExperience(oldLevel, oldXPLevel);
if (totalOldXP == 0) {
continue;
}
int[] newExperienceValues = mcMMO.getFormulaManager().calculateNewLevel(primarySkillType, (int) Math.floor(totalOldXP / ExperienceConfig.getInstance().getExpModifier()), formulaType);
int newLevel = newExperienceValues[0];
int newXPlevel = newExperienceValues[1];
mcMMO.p.debug(" Skill: " + primarySkillType.toString());
mcMMO.p.debug(" OLD:");
mcMMO.p.debug(" Level: " + oldLevel);
mcMMO.p.debug(" XP " + oldXPLevel);
mcMMO.p.debug(" Total XP " + totalOldXP);
mcMMO.p.debug(" NEW:");
mcMMO.p.debug(" Level " + newLevel);
mcMMO.p.debug(" XP " + newXPlevel);
mcMMO.p.debug("------------------------------------------------------------------------");
profile.modifySkill(primarySkillType, newLevel);
profile.setSkillXpLevel(primarySkillType, newXPlevel);
}
}
}

View File

@ -0,0 +1,102 @@
package com.gmail.nossr50.core.runnables.database;
import com.gmail.nossr50.core.config.skills.HiddenConfig;
import com.gmail.nossr50.core.data.database.DatabaseManager;
import com.gmail.nossr50.core.datatypes.database.UpgradeType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.uuid.UUIDFetcher;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
public class UUIDUpdateAsyncTask extends BukkitRunnable {
private mcMMO plugin;
private static final int MAX_LOOKUP = Math.max(HiddenConfig.getInstance().getUUIDConvertAmount(), 100);
private static final int RATE_LIMIT = HiddenConfig.getInstance().getMojangRateLimit();
private static final long LIMIT_PERIOD = HiddenConfig.getInstance().getMojangLimitPeriod();
private static final int BATCH_SIZE = MAX_LOOKUP * 3;
private List<String> userNames;
private int size;
private int checkedUsers;
private long startMillis;
public UUIDUpdateAsyncTask(mcMMO plugin, List<String> userNames) {
this.plugin = plugin;
this.userNames = userNames;
this.checkedUsers = 0;
this.startMillis = System.currentTimeMillis();
}
@Override
public void run() {
size = userNames.size();
plugin.getLogger().info("Starting to check and update UUIDs, total amount of users: " + size);
List<String> userNamesSection;
Map<String, UUID> fetchedUUIDs = new HashMap<String, UUID>();
while (size != 0) {
if (checkedUsers + 100 > RATE_LIMIT) {
try {
Thread.sleep(LIMIT_PERIOD);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
startMillis = System.currentTimeMillis();
checkedUsers = 0;
}
if (size > MAX_LOOKUP) {
userNamesSection = userNames.subList(size - MAX_LOOKUP, size);
size -= MAX_LOOKUP;
}
else {
userNamesSection = userNames.subList(0, size);
size = 0;
}
try {
fetchedUUIDs.putAll(new UUIDFetcher(userNamesSection).call());
}
catch (Exception e) {
// Handle 429
if (e.getMessage().contains("429")) {
size += userNamesSection.size();
try {
Thread.sleep(LIMIT_PERIOD);
} catch (InterruptedException ex) {
e.printStackTrace();
return;
}
continue;
}
plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUIDs!", e);
return;
}
checkedUsers += userNamesSection.size();
userNamesSection.clear();
size = userNames.size();
Misc.printProgress(checkedUsers, DatabaseManager.progressInterval, startMillis);
if (fetchedUUIDs.size() >= BATCH_SIZE) {
mcMMO.getDatabaseManager().saveUserUUIDs(fetchedUUIDs);
fetchedUUIDs = new HashMap<String, UUID>();
}
}
if (fetchedUUIDs.size() == 0 || mcMMO.getDatabaseManager().saveUserUUIDs(fetchedUUIDs)) {
mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_UUIDS);
plugin.getLogger().info("UUID upgrade completed!");
}
}
}

View File

@ -0,0 +1,21 @@
package com.gmail.nossr50.core.runnables.database;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.mcMMO;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.concurrent.locks.ReentrantLock;
public class UserPurgeTask extends BukkitRunnable {
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
lock.lock();
mcMMO.getDatabaseManager().purgePowerlessUsers();
if (Config.getInstance().getOldUsersCutoff() != -1) {
mcMMO.getDatabaseManager().purgeOldUsers();
}
lock.unlock();
}
}

View File

@ -0,0 +1,58 @@
package com.gmail.nossr50.core.runnables.items;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.util.ChimaeraWing;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
public class ChimaeraWingWarmup extends BukkitRunnable {
private McMMOPlayer mcMMOPlayer;
public ChimaeraWingWarmup(McMMOPlayer mcMMOPlayer) {
this.mcMMOPlayer = mcMMOPlayer;
}
@Override
public void run() {
checkChimaeraWingTeleport();
}
private void checkChimaeraWingTeleport() {
Player player = mcMMOPlayer.getPlayer();
Location previousLocation = mcMMOPlayer.getTeleportCommenceLocation();
if (player.getLocation().distanceSquared(previousLocation) > 1.0 || !player.getInventory().containsAtLeast(ChimaeraWing.getChimaeraWing(0), 1)) {
player.sendMessage(LocaleLoader.getString("Teleport.Cancelled"));
mcMMOPlayer.setTeleportCommenceLocation(null);
return;
}
ItemStack inHand = player.getInventory().getItemInMainHand();
if (!ItemUtils.isChimaeraWing(inHand) || inHand.getAmount() < Config.getInstance().getChimaeraUseCost()) {
player.sendMessage(LocaleLoader.getString("Skills.NeedMore", LocaleLoader.getString("Item.ChimaeraWing.Name")));
return;
}
long recentlyHurt = mcMMOPlayer.getRecentlyHurt();
int hurtCooldown = Config.getInstance().getChimaeraRecentlyHurtCooldown();
if (hurtCooldown > 0) {
int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
if (timeRemaining > 0) {
player.sendMessage(LocaleLoader.getString("Item.Injured.Wait", timeRemaining));
return;
}
}
ChimaeraWing.chimaeraExecuteTeleport();
}
}

View File

@ -0,0 +1,56 @@
package com.gmail.nossr50.core.runnables.items;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class TeleportationWarmup extends BukkitRunnable {
private McMMOPlayer mcMMOPlayer;
private McMMOPlayer mcMMOTarget;
public TeleportationWarmup(McMMOPlayer mcMMOPlayer, McMMOPlayer mcMMOTarget) {
this.mcMMOPlayer = mcMMOPlayer;
this.mcMMOTarget = mcMMOTarget;
}
@Override
public void run() {
Player teleportingPlayer = mcMMOPlayer.getPlayer();
Player targetPlayer = mcMMOTarget.getPlayer();
Location previousLocation = mcMMOPlayer.getTeleportCommenceLocation();
Location newLocation = mcMMOPlayer.getPlayer().getLocation();
long recentlyHurt = mcMMOPlayer.getRecentlyHurt();
mcMMOPlayer.setTeleportCommenceLocation(null);
if (!PartyManager.inSameParty(teleportingPlayer, targetPlayer)) {
teleportingPlayer.sendMessage(LocaleLoader.getString("Party.NotInYourParty", targetPlayer.getName()));
return;
}
if (newLocation.distanceSquared(previousLocation) > 1.0) {
teleportingPlayer.sendMessage(LocaleLoader.getString("Teleport.Cancelled"));
return;
}
int hurtCooldown = Config.getInstance().getPTPCommandRecentlyHurtCooldown();
if (hurtCooldown > 0) {
int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, teleportingPlayer);
if (timeRemaining > 0) {
teleportingPlayer.sendMessage(LocaleLoader.getString("Item.Injured.Wait", timeRemaining));
return;
}
}
EventUtils.handlePartyTeleportEvent(teleportingPlayer, targetPlayer);
}
}

View File

@ -0,0 +1,45 @@
package com.gmail.nossr50.core.runnables.party;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.PartyManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;
public class PartyAutoKickTask extends BukkitRunnable {
private final static long KICK_TIME = 24L * 60L * 60L * 1000L * Config.getInstance().getAutoPartyKickTime();
@Override
public void run() {
HashMap<OfflinePlayer, Party> toRemove = new HashMap<OfflinePlayer, Party>();
List<UUID> processedPlayers = new ArrayList<UUID>();
long currentTime = System.currentTimeMillis();
for (Party party : PartyManager.getParties()) {
for (UUID memberUniqueId : party.getMembers().keySet()) {
OfflinePlayer member = mcMMO.p.getServer().getOfflinePlayer(memberUniqueId);
boolean isProcessed = processedPlayers.contains(memberUniqueId);
if ((!member.isOnline() && (currentTime - member.getLastPlayed() > KICK_TIME)) || isProcessed) {
toRemove.put(member, party);
}
if (!isProcessed) {
processedPlayers.add(memberUniqueId);
}
}
}
for (Entry<OfflinePlayer, Party> entry : toRemove.entrySet()) {
PartyManager.removeFromParty(entry.getKey(), entry.getValue());
}
}
}

View File

@ -0,0 +1,50 @@
package com.gmail.nossr50.core.runnables.party;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.party.Party;
import com.gmail.nossr50.core.locale.LocaleLoader;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PartyChatTask extends BukkitRunnable {
private Plugin plugin;
private Party party;
private String senderName;
private String displayName;
private String message;
public PartyChatTask(Plugin plugin, Party party, String senderName, String displayName, String message) {
this.plugin = plugin;
this.party = party;
this.senderName = senderName;
this.displayName = displayName;
this.message = message;
}
@Override
public void run() {
if (Config.getInstance().getPartyChatColorLeaderName() && senderName.equalsIgnoreCase(party.getLeader().getPlayerName())) {
message = message.replaceFirst(Pattern.quote(displayName), ChatColor.GOLD + Matcher.quoteReplacement(displayName) + ChatColor.RESET);
}
for (Player member : party.getOnlineMembers()) {
member.sendMessage(message);
}
if (party.getAlly() != null) {
for (Player member : party.getAlly().getOnlineMembers()) {
String allyPrefix = LocaleLoader.formatString(Config.getInstance().getPartyChatPrefixAlly());
member.sendMessage(allyPrefix + message);
}
}
plugin.getServer().getConsoleSender().sendMessage(ChatColor.stripColor("[mcMMO] [P]<" + party.getName() + ">" + message));
}
}

View File

@ -0,0 +1,14 @@
package com.gmail.nossr50.core.runnables.player;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.scheduler.BukkitRunnable;
public class ClearRegisteredXPGainTask extends BukkitRunnable {
@Override
public void run() {
for (McMMOPlayer mcMMOPlayer : UserManager.getPlayers()) {
mcMMOPlayer.getProfile().purgeExpiredXpGains();
}
}
}

View File

@ -0,0 +1,96 @@
package com.gmail.nossr50.core.runnables.player;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.core.runnables.commands.McScoreboardKeepTask;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.core.data.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class PlayerProfileLoadingTask extends BukkitRunnable {
private static final int MAX_TRIES = 5;
private final Player player;
private int attempt = 0;
public PlayerProfileLoadingTask(Player player) {
this.player = player;
}
private PlayerProfileLoadingTask(Player player, int attempt) {
this.player = player;
this.attempt = attempt;
}
// WARNING: ASYNC TASK
// DO NOT MODIFY THE McMMOPLAYER FROM THIS CODE
@Override
public void run() {
// Quit if they logged out
if (!player.isOnline()) {
mcMMO.p.getLogger().info("Aborting profile loading recovery for " + player.getName() + " - player logged out");
return;
}
// Increment attempt counter and try
attempt++;
PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(player.getName(), player.getUniqueId(), true);
// If successful, schedule the apply
if (profile.isLoaded()) {
new ApplySuccessfulProfile(new McMMOPlayer(player, profile)).runTask(mcMMO.p);
return;
}
// If we've failed five times, give up
if (attempt >= MAX_TRIES) {
mcMMO.p.getLogger().severe("Giving up on attempting to load the PlayerProfile for " + player.getName());
mcMMO.p.getServer().broadcast(LocaleLoader.getString("Profile.Loading.AdminFailureNotice", player.getName()), Server.BROADCAST_CHANNEL_ADMINISTRATIVE);
player.sendMessage(LocaleLoader.getString("Profile.Loading.Failure").split("\n"));
return;
}
new PlayerProfileLoadingTask(player, attempt).runTaskLaterAsynchronously(mcMMO.p, 100 * attempt);
}
private class ApplySuccessfulProfile extends BukkitRunnable {
private final McMMOPlayer mcMMOPlayer;
private ApplySuccessfulProfile(McMMOPlayer mcMMOPlayer) {
this.mcMMOPlayer = mcMMOPlayer;
}
// Synchronized task
// No database access permitted
@Override
public void run() {
if (!player.isOnline()) {
mcMMO.p.getLogger().info("Aborting profile loading recovery for " + player.getName() + " - player logged out");
return;
}
mcMMOPlayer.setupPartyData();
UserManager.track(mcMMOPlayer);
mcMMOPlayer.actualizeRespawnATS();
if (Config.getInstance().getScoreboardsEnabled()) {
ScoreboardManager.setupPlayer(player);
if (Config.getInstance().getShowStatsAfterLogin()) {
ScoreboardManager.enablePlayerStatsScoreboard(player);
new McScoreboardKeepTask(player).runTaskLater(mcMMO.p, 1 * Misc.TICK_CONVERSION_FACTOR);
}
}
if (Config.getInstance().getShowProfileLoadedMessage()) {
player.sendMessage(LocaleLoader.getString("Profile.Loading.Success"));
}
}
}
}

View File

@ -0,0 +1,17 @@
package com.gmail.nossr50.core.runnables.player;
import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
import org.bukkit.scheduler.BukkitRunnable;
public class PlayerProfileSaveTask extends BukkitRunnable {
private PlayerProfile playerProfile;
public PlayerProfileSaveTask(PlayerProfile playerProfile) {
this.playerProfile = playerProfile;
}
@Override
public void run() {
playerProfile.save();
}
}

View File

@ -0,0 +1,18 @@
package com.gmail.nossr50.core.runnables.player;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@SuppressWarnings("deprecation")
public class PlayerUpdateInventoryTask extends BukkitRunnable {
private Player player;
public PlayerUpdateInventoryTask(Player player) {
this.player = player;
}
@Override
public void run() {
player.updateInventory();
}
}

View File

@ -0,0 +1,13 @@
package com.gmail.nossr50.core.runnables.player;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import org.bukkit.scheduler.BukkitRunnable;
public class PowerLevelUpdatingTask extends BukkitRunnable {
@Override
public void run() {
if (!ScoreboardManager.powerLevelHeartbeat()) {
this.cancel();
}
}
}

View File

@ -0,0 +1,29 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.SuperAbilityType;
import com.gmail.nossr50.util.player.NotificationManager;
import org.bukkit.scheduler.BukkitRunnable;
public class AbilityCooldownTask extends BukkitRunnable {
private McMMOPlayer mcMMOPlayer;
private SuperAbilityType ability;
public AbilityCooldownTask(McMMOPlayer mcMMOPlayer, SuperAbilityType ability) {
this.mcMMOPlayer = mcMMOPlayer;
this.ability = ability;
}
@Override
public void run() {
if (mcMMOPlayer.getAbilityInformed(ability)) {
return;
}
mcMMOPlayer.setAbilityInformed(ability, true);
NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.ABILITY_REFRESHED, ability.getAbilityRefresh());
//mcMMOPlayer.getPlayer().sendMessage(ability.getAbilityRefresh());
}
}

View File

@ -0,0 +1,82 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.SuperAbilityType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.PerksUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class AbilityDisableTask extends BukkitRunnable {
private McMMOPlayer mcMMOPlayer;
private SuperAbilityType ability;
public AbilityDisableTask(McMMOPlayer mcMMOPlayer, SuperAbilityType ability) {
this.mcMMOPlayer = mcMMOPlayer;
this.ability = ability;
}
@Override
public void run() {
if (!mcMMOPlayer.getAbilityMode(ability)) {
return;
}
Player player = mcMMOPlayer.getPlayer();
switch (ability) {
case SUPER_BREAKER:
case GIGA_DRILL_BREAKER:
SkillUtils.handleAbilitySpeedDecrease(player);
// Fallthrough
case BERSERK:
if (Config.getInstance().getRefreshChunksEnabled()) {
resendChunkRadiusAt(player, 1);
}
// Fallthrough
default:
break;
}
EventUtils.callAbilityDeactivateEvent(player, ability);
mcMMOPlayer.setAbilityMode(ability, false);
mcMMOPlayer.setAbilityInformed(ability, false);
ParticleEffectUtils.playAbilityDisabledEffect(player);
if (mcMMOPlayer.useChatNotifications()) {
//player.sendMessage(ability.getAbilityOff());
NotificationManager.sendPlayerInformation(player, NotificationType.ABILITY_OFF, ability.getAbilityOff());
}
SkillUtils.sendSkillMessage(player, NotificationType.SUPER_ABILITY_ALERT_OTHERS, ability.getAbilityPlayerOff());
new AbilityCooldownTask(mcMMOPlayer, ability).runTaskLaterAsynchronously(mcMMO.p, PerksUtils.handleCooldownPerks(player, ability.getCooldown()) * Misc.TICK_CONVERSION_FACTOR);
}
private void resendChunkRadiusAt(Player player, int radius) {
Chunk chunk = player.getLocation().getChunk();
World world = player.getWorld();
int chunkX = chunk.getX();
int chunkZ = chunk.getZ();
for (int x = chunkX - radius; x <= chunkX + radius; x++) {
for (int z = chunkZ - radius; z <= chunkZ + radius; z++) {
world.refreshChunk(x, z);
}
}
}
}

View File

@ -0,0 +1,39 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.skills.primary.alchemy.Alchemy;
import com.gmail.nossr50.core.skills.primary.alchemy.AlchemyPotionBrewer;
import org.bukkit.Location;
import org.bukkit.block.BrewingStand;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Arrays;
public class AlchemyBrewCheckTask extends BukkitRunnable {
private Player player;
private BrewingStand brewingStand;
private ItemStack[] oldInventory;
public AlchemyBrewCheckTask(Player player, BrewingStand brewingStand) {
this.player = player;
this.brewingStand = brewingStand;
this.oldInventory = Arrays.copyOfRange(brewingStand.getInventory().getContents(), 0, 4);
}
@Override
public void run() {
Location location = brewingStand.getLocation();
ItemStack[] newInventory = Arrays.copyOfRange(brewingStand.getInventory().getContents(), 0, 4);
boolean validBrew = brewingStand.getFuelLevel() > 0 && AlchemyPotionBrewer.isValidBrew(player, newInventory);
if (Alchemy.brewingStandMap.containsKey(location)) {
if (oldInventory[Alchemy.INGREDIENT_SLOT] == null || newInventory[Alchemy.INGREDIENT_SLOT] == null || !oldInventory[Alchemy.INGREDIENT_SLOT].isSimilar(newInventory[Alchemy.INGREDIENT_SLOT]) || !validBrew) {
Alchemy.brewingStandMap.get(location).cancelBrew();
}
}
else if (validBrew) {
Alchemy.brewingStandMap.put(location, new AlchemyBrewTask(brewingStand, player));
}
}
}

View File

@ -0,0 +1,117 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.events.skills.alchemy.McMMOPlayerBrewEvent;
import com.gmail.nossr50.events.skills.alchemy.McMMOPlayerCatalysisEvent;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.core.skills.primary.alchemy.Alchemy;
import com.gmail.nossr50.core.skills.primary.alchemy.AlchemyPotionBrewer;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.block.BrewingStand;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class AlchemyBrewTask extends BukkitRunnable {
private static double DEFAULT_BREW_SPEED = 1.0;
private static int DEFAULT_BREW_TICKS = 400;
private BlockState brewingStand;
private Location location;
private double brewSpeed;
private double brewTimer;
private Player player;
private int fuel;
private boolean firstRun = true;
public AlchemyBrewTask(BlockState brewingStand, Player player) {
this.brewingStand = brewingStand;
this.location = brewingStand.getLocation();
this.player = player;
brewSpeed = DEFAULT_BREW_SPEED;
brewTimer = DEFAULT_BREW_TICKS;
if (player != null && !Misc.isNPCEntity(player) && Permissions.isSubSkillEnabled(player, SubSkillType.ALCHEMY_CATALYSIS)) {
double catalysis = UserManager.getPlayer(player).getAlchemyManager().calculateBrewSpeed(Permissions.lucky(player, PrimarySkillType.ALCHEMY));
McMMOPlayerCatalysisEvent event = new McMMOPlayerCatalysisEvent(player, catalysis);
mcMMO.p.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
brewSpeed = catalysis;
}
}
if (Alchemy.brewingStandMap.containsKey(location)) {
Alchemy.brewingStandMap.get(location).cancel();
}
fuel = ((BrewingStand) brewingStand).getFuelLevel();
if (((BrewingStand) brewingStand).getBrewingTime() == -1) // Only decrement on our end if it isn't a vanilla ingredient.
fuel--;
Alchemy.brewingStandMap.put(location, this);
this.runTaskTimer(mcMMO.p, 1, 1);
}
@Override
public void run() {
if (player == null || !player.isValid() || brewingStand == null || brewingStand.getType() != Material.BREWING_STAND || !AlchemyPotionBrewer.isValidIngredient(player, ((BrewingStand) brewingStand).getInventory().getContents()[Alchemy.INGREDIENT_SLOT])) {
if (Alchemy.brewingStandMap.containsKey(location)) {
Alchemy.brewingStandMap.remove(location);
}
this.cancel();
return;
}
if (firstRun) {
firstRun = false;
((BrewingStand) brewingStand).setFuelLevel(fuel);
}
brewTimer -= brewSpeed;
// Vanilla potion brewing completes when BrewingTime == 1
if (brewTimer < Math.max(brewSpeed, 2)) {
this.cancel();
finish();
}
else {
((BrewingStand) brewingStand).setBrewingTime((int) brewTimer);
}
}
private void finish() {
McMMOPlayerBrewEvent event = new McMMOPlayerBrewEvent(player, brewingStand);
mcMMO.p.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
AlchemyPotionBrewer.finishBrewing(brewingStand, player, false);
}
Alchemy.brewingStandMap.remove(location);
}
public void finishImmediately() {
this.cancel();
AlchemyPotionBrewer.finishBrewing(brewingStand, player, true);
Alchemy.brewingStandMap.remove(location);
}
public void cancelBrew() {
this.cancel();
((BrewingStand) brewingStand).setBrewingTime(-1);
Alchemy.brewingStandMap.remove(location);
}
}

View File

@ -0,0 +1,56 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.HolidayManager;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.bukkit.ChatColor;
import org.bukkit.Statistic;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class AprilTask extends BukkitRunnable {
@Override
public void run() {
if (!mcMMO.getHolidayManager().isAprilFirst()) {
this.cancel();
return;
}
for (Player player : mcMMO.p.getServer().getOnlinePlayers()) {
int random = Misc.getRandom().nextInt(40) + 11;
int betterRandom = Misc.getRandom().nextInt(2000);
if (betterRandom == 0) {
SoundManager.sendSound(player, player.getLocation(), SoundType.LEVEL_UP);
player.sendMessage(unknown("superskill") + " skill increased by 1. Total (" + unknown("12") + ")");
fireworksShow(player);
}
for (Statistic statistic : mcMMO.getHolidayManager().movementStatistics) {
if (player.getStatistic(statistic) > 0 && player.getStatistic(statistic) % random == 0) {
mcMMO.getHolidayManager().levelUpApril(player, HolidayManager.FakeSkillType.getByStatistic(statistic));
break;
}
}
}
}
private void fireworksShow(final Player player) {
final int firework_amount = 10;
for (int i = 0; i < firework_amount; i++) {
int delay = (int) (Misc.getRandom().nextDouble() * 3 * Misc.TICK_CONVERSION_FACTOR) + 4;
mcMMO.p.getServer().getScheduler().runTaskLater(mcMMO.p, new Runnable() {
@Override
public void run() {
mcMMO.getHolidayManager().spawnFireworks(player);
}
}, delay);
}
}
private String unknown(String string) {
return ChatColor.MAGIC + string + ChatColor.RESET + ChatColor.YELLOW;
}
}

View File

@ -0,0 +1,44 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
public class AwardCombatXpTask extends BukkitRunnable {
private McMMOPlayer mcMMOPlayer;
private double baseXp;
private PrimarySkillType primarySkillType;
private LivingEntity target;
private XPGainReason xpGainReason;
private double baseHealth;
public AwardCombatXpTask(McMMOPlayer mcMMOPlayer, PrimarySkillType primarySkillType, double baseXp, LivingEntity target, XPGainReason xpGainReason) {
this.mcMMOPlayer = mcMMOPlayer;
this.primarySkillType = primarySkillType;
this.baseXp = baseXp;
this.target = target;
this.xpGainReason = xpGainReason;
baseHealth = target.getHealth();
}
@Override
public void run() {
double health = target.getHealth();
double damage = baseHealth - health;
// May avoid negative xp, we don't know what other plugins do with the entity health
if (damage <= 0) {
return;
}
// Don't reward the player for overkills
if (health < 0) {
damage += health;
}
mcMMOPlayer.beginXpGain(primarySkillType, (int) (damage * baseXp), xpGainReason, XPGainSource.SELF);
}
}

View File

@ -0,0 +1,18 @@
package com.gmail.nossr50.core.runnables.skills;
import org.bukkit.entity.LivingEntity;
public class BleedContainer {
public int bleedTicks;
public int bleedRank;
public LivingEntity target;
public LivingEntity damageSource;
public BleedContainer(LivingEntity target, int bleedTicks, int bleedRank, LivingEntity damageSource)
{
this.target = target;
this.bleedTicks = bleedTicks;
this.bleedRank = bleedRank;
this.damageSource = damageSource;
}
}

View File

@ -0,0 +1,119 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.MobHealthbarUtils;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class BleedTimerTask extends BukkitRunnable {
private static Map<LivingEntity, BleedContainer> bleedList = new HashMap<LivingEntity, BleedContainer>();
@Override
public void run() {
Iterator<Entry<LivingEntity, BleedContainer>> bleedIterator = bleedList.entrySet().iterator();
while (bleedIterator.hasNext()) {
Entry<LivingEntity, BleedContainer> containerEntry = bleedIterator.next();
LivingEntity target = containerEntry.getKey();
int bleedTicks = containerEntry.getValue().bleedTicks;
if (containerEntry.getValue().bleedTicks <= 0 || !target.isValid()) {
bleedIterator.remove();
continue;
}
double damage;
if (target instanceof Player) {
damage = AdvancedConfig.getInstance().getRuptureDamagePlayer();
//Above Bleed Rank 3 deals 50% more damage
if (containerEntry.getValue().bleedRank >= 3)
damage = damage * 1.5;
Player player = (Player) target;
if (!player.isOnline()) {
continue;
}
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Bleeding.Stopped");
} else {
damage = AdvancedConfig.getInstance().getRuptureDamageMobs();
//Above Bleed Rank 3 deals 50% more damage
if (containerEntry.getValue().bleedRank >= 3)
damage = damage * 1.5;
MobHealthbarUtils.handleMobHealthbars(target, damage, mcMMO.p); //Update health bars
}
CombatUtils.dealNoInvulnerabilityTickDamage(target, damage, containerEntry.getValue().damageSource);
//Play Bleed Sound
SoundManager.worldSendSound(target.getWorld(), target.getLocation(), SoundType.BLEED);
ParticleEffectUtils.playBleedEffect(target);
//Lower Bleed Ticks
BleedContainer loweredBleedContainer = copyContainer(containerEntry.getValue());
loweredBleedContainer.bleedTicks -= 1;
containerEntry.setValue(loweredBleedContainer);
}
}
public static BleedContainer copyContainer(BleedContainer container)
{
LivingEntity target = container.target;
LivingEntity source = container.damageSource;
int bleedTicks = container.bleedTicks;
int bleedRank = container.bleedRank;
BleedContainer newContainer = new BleedContainer(target, bleedTicks, bleedRank, source);
return newContainer;
}
/**
* Instantly Bleed out a LivingEntity
*
* @param entity LivingEntity to bleed out
*/
public static void bleedOut(LivingEntity entity) {
/*
* Don't remove anything from the list outside of run()
*/
if (bleedList.containsKey(entity)) {
CombatUtils.dealNoInvulnerabilityTickDamage(entity, bleedList.get(entity).bleedTicks * 2, bleedList.get(entity).damageSource);
}
}
/**
* Add a LivingEntity to the bleedList if it is not in it.
*
* @param entity LivingEntity to add
* @param ticks Number of bleeding ticks
*/
public static void add(LivingEntity entity, LivingEntity attacker, int ticks, int bleedRank) {
BleedContainer newBleedContainer = new BleedContainer(entity, ticks, bleedRank, attacker);
bleedList.put(entity, newBleedContainer);
}
public static boolean isBleeding(LivingEntity entity) {
return bleedList.containsKey(entity);
}
}

View File

@ -0,0 +1,39 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.util.experience.ExperienceBarManager;
import org.bukkit.scheduler.BukkitRunnable;
public class ExperienceBarHideTask extends BukkitRunnable {
public final McMMOPlayer mcMMOPlayer;
public final PrimarySkillType primarySkillType;
public final ExperienceBarManager experienceBarManagerRef;
public ExperienceBarHideTask(ExperienceBarManager experienceBarManagerRef, McMMOPlayer mcMMOPlayer, PrimarySkillType primarySkillType)
{
this.experienceBarManagerRef = experienceBarManagerRef;
this.mcMMOPlayer = mcMMOPlayer;
this.primarySkillType = primarySkillType;
}
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
if(experienceBarManagerRef == null || mcMMOPlayer == null)
return;
experienceBarManagerRef.hideExperienceBar(primarySkillType);
experienceBarManagerRef.clearTask(primarySkillType);
}
}

View File

@ -0,0 +1,17 @@
package com.gmail.nossr50.core.runnables.skills;
import org.bukkit.block.BlockState;
import org.bukkit.scheduler.BukkitRunnable;
public class HerbalismBlockUpdaterTask extends BukkitRunnable {
private BlockState blockState;
public HerbalismBlockUpdaterTask(BlockState blockState) {
this.blockState = blockState;
}
@Override
public void run() {
blockState.update(true);
}
}

View File

@ -0,0 +1,41 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.util.player.NotificationManager;
import org.bukkit.scheduler.BukkitRunnable;
public class SkillUnlockNotificationTask extends BukkitRunnable {
private McMMOPlayer mcMMOPlayer;
private SubSkillType subSkillType;
private int rank;
/**
* Notify a player about a newly unlocked subskill
* @param mcMMOPlayer target player
* @param subSkillType the subskill that they just unlocked
* @param rank the rank of the subskill
*/
public SkillUnlockNotificationTask(McMMOPlayer mcMMOPlayer, SubSkillType subSkillType, int rank)
{
this.mcMMOPlayer = mcMMOPlayer;
this.subSkillType = subSkillType;
this.rank = rank;
}
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
//mcMMOPlayer.getPlayer().sendTitle(subSkillType.getLocaleName(), "Rank "+rank, 7, 20, 7);
NotificationManager.sendPlayerUnlockNotification(mcMMOPlayer, subSkillType);
}
}

View File

@ -0,0 +1,31 @@
package com.gmail.nossr50.core.runnables.skills;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.ToolType;
import com.gmail.nossr50.util.player.NotificationManager;
import org.bukkit.scheduler.BukkitRunnable;
public class ToolLowerTask extends BukkitRunnable {
private McMMOPlayer mcMMOPlayer;
private ToolType tool;
public ToolLowerTask(McMMOPlayer mcMMOPlayer, ToolType tool) {
this.mcMMOPlayer = mcMMOPlayer;
this.tool = tool;
}
@Override
public void run() {
if (!mcMMOPlayer.getToolPreparationMode(tool)) {
return;
}
mcMMOPlayer.setToolPreparationMode(tool, false);
if (Config.getInstance().getAbilityMessagesEnabled()) {
NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.TOOL, tool.getLowerTool());
}
}
}

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
public enum ItemType {
ARMOR,

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
import org.bukkit.Material;

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes;
package com.gmail.nossr50.core.skills;
public enum MobHealthbarType {
HEARTS,

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
public enum ModConfigType {
BLOCKS,

View File

@ -1,5 +1,6 @@
package com.gmail.nossr50.core.datatypes.skills.alchemy;
package com.gmail.nossr50.core.skills;
import com.gmail.nossr50.core.skills.primary.alchemy.AlchemyPotion;
import org.bukkit.Material;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;

View File

@ -0,0 +1,51 @@
package com.gmail.nossr50.core.skills;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
public abstract class SkillManager {
protected McMMOPlayer mcMMOPlayer;
protected PrimarySkillType skill;
public SkillManager(McMMOPlayer mcMMOPlayer, PrimarySkillType skill) {
this.mcMMOPlayer = mcMMOPlayer;
this.skill = skill;
}
public Player getPlayer() {
return mcMMOPlayer.getPlayer();
}
public int getSkillLevel() {
return mcMMOPlayer.getSkillLevel(skill);
}
/**
* Applies XP to a player, provides SELF as an XpGainSource source
* @param xp amount of XP to apply
* @param xpGainReason the reason for the XP gain
* @deprecated use applyXpGain(float, XPGainReason, XPGainSource)
*/
@Deprecated
public void applyXpGain(float xp, XPGainReason xpGainReason) {
mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
}
/**
* Applies XP to a player
* @param xp amount of XP to apply
* @param xpGainReason the reason for the XP gain
* @param xpGainSource the source of the XP
*/
public void applyXpGain(float xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, xpGainSource);
}
public XPGainReason getXPGainReason(LivingEntity target, Entity damager) {
return (damager instanceof Player && target instanceof Player) ? XPGainReason.PVP : XPGainReason.PVE;
}
}

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
public class SubSkillFlags {
/*

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.StringUtils;

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.util.BlockUtils;

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills;
package com.gmail.nossr50.core.skills;
import com.gmail.nossr50.util.ItemUtils;
import org.bukkit.Material;

View File

@ -0,0 +1,61 @@
package com.gmail.nossr50.core.skills.child;
import com.gmail.nossr50.core.config.skills.AutoUpdateConfigLoader;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.util.StringUtils;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.EnumSet;
public class ChildConfig extends AutoUpdateConfigLoader {
public ChildConfig() {
super("child.yml");
loadKeys();
}
@Override
protected void loadKeys() {
config.setDefaults(YamlConfiguration.loadConfiguration(plugin.getResourceAsReader("child.yml")));
FamilyTree.clearRegistrations(); // when reloading, need to clear statics
for (PrimarySkillType skill : PrimarySkillType.CHILD_SKILLS) {
plugin.debug("Finding parents of " + skill.name());
EnumSet<PrimarySkillType> parentSkills = EnumSet.noneOf(PrimarySkillType.class);
boolean useDefaults = false; // If we had an error we back out and use defaults
for (String name : config.getStringList(StringUtils.getCapitalized(skill.name()))) {
try {
PrimarySkillType parentSkill = PrimarySkillType.valueOf(name.toUpperCase());
FamilyTree.enforceNotChildSkill(parentSkill);
parentSkills.add(parentSkill);
}
catch (IllegalArgumentException ex) {
plugin.getLogger().warning(name + " is not a valid skill type, or is a child skill!");
useDefaults = true;
break;
}
}
if (useDefaults) {
parentSkills.clear();
for (String name : config.getDefaults().getStringList(StringUtils.getCapitalized(skill.name()))) {
/* We do less checks in here because it's from inside our jar.
* If they're dedicated enough to have modified it, they can have the errors it may produce.
* Alternatively, this can be used to allow child skills to be parent skills, provided there are no circular dependencies this is an advanced sort of configuration.
*/
parentSkills.add(PrimarySkillType.valueOf(name.toUpperCase()));
}
}
// Register them
for (PrimarySkillType parentSkill : parentSkills) {
plugin.debug("Registering " + parentSkill.name() + " as parent of " + skill.name());
FamilyTree.registerParent(skill, parentSkill);
}
}
FamilyTree.closeRegistration();
}
}

View File

@ -0,0 +1,53 @@
package com.gmail.nossr50.core.skills.child;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Set;
public class FamilyTree {
private static HashMap<PrimarySkillType, Set<PrimarySkillType>> tree = new HashMap<PrimarySkillType, Set<PrimarySkillType>>();
public static Set<PrimarySkillType> getParents(PrimarySkillType childSkill) {
enforceChildSkill(childSkill);
// We do not check if we have the child skill in question, as not having it would mean we did something wrong, and an NPE is desired.
return tree.get(childSkill);
}
protected static void registerParent(PrimarySkillType childSkill, PrimarySkillType parentSkill) {
enforceChildSkill(childSkill);
enforceNotChildSkill(parentSkill);
if (!tree.containsKey(childSkill)) {
tree.put(childSkill, EnumSet.noneOf(PrimarySkillType.class));
}
tree.get(childSkill).add(parentSkill);
}
protected static void closeRegistration() {
for (PrimarySkillType childSkill : tree.keySet()) {
Set<PrimarySkillType> immutableSet = Collections.unmodifiableSet(tree.get(childSkill));
tree.put(childSkill, immutableSet);
}
}
protected static void clearRegistrations() {
tree.clear();
}
protected static void enforceChildSkill(PrimarySkillType skill) {
if (!skill.isChildSkill()) {
throw new IllegalArgumentException(skill.name() + " is not a child skill!");
}
}
protected static void enforceNotChildSkill(PrimarySkillType skill) {
if (skill.isChildSkill()) {
throw new IllegalArgumentException(skill.name() + " is a child skill!");
}
}
}

View File

@ -0,0 +1,23 @@
package com.gmail.nossr50.core.skills.child.salvage;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.config.skills.Config;
import org.bukkit.Material;
public class Salvage {
public static Material anvilMaterial = Config.getInstance().getSalvageAnvilMaterial();
/*public static int salvageMaxPercentageLevel = AdvancedConfig.getInstance().getSalvageMaxPercentageLevel();
public static double salvageMaxPercentage = AdvancedConfig.getInstance().getSalvageMaxPercentage();
public static int advancedSalvageUnlockLevel = RankUtils.getRankUnlockLevel(SubSkillType.SALVAGE_ADVANCED_SALVAGE, 1);*/
public static boolean arcaneSalvageDowngrades = AdvancedConfig.getInstance().getArcaneSalvageEnchantDowngradeEnabled();
public static boolean arcaneSalvageEnchantLoss = AdvancedConfig.getInstance().getArcaneSalvageEnchantLossEnabled();
protected static int calculateSalvageableAmount(short currentDurability, short maxDurability, int baseAmount) {
double percentDamaged = (maxDurability <= 0) ? 1D : (double) (maxDurability - currentDurability) / maxDurability;
return (int) Math.floor(baseAmount * percentDamaged);
}
}

View File

@ -0,0 +1,298 @@
package com.gmail.nossr50.core.skills.child.salvage;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.locale.LocaleLoader;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.core.skills.child.salvage.salvageables.Salvageable;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import java.util.Map;
import java.util.Map.Entry;
public class SalvageManager extends SkillManager {
private boolean placedAnvil;
private int lastClick;
public SalvageManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.SALVAGE);
}
/**
* Handles notifications for placing an anvil.
*/
public void placedAnvilCheck() {
Player player = getPlayer();
if (getPlacedAnvil()) {
return;
}
if (Config.getInstance().getSalvageAnvilMessagesEnabled()) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Salvage.Listener.Anvil");
}
if (Config.getInstance().getSalvageAnvilPlaceSoundsEnabled()) {
SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
}
togglePlacedAnvil();
}
public void handleSalvage(Location location, ItemStack item) {
Player player = getPlayer();
Salvageable salvageable = mcMMO.getSalvageableManager().getSalvageable(item.getType());
if (item.getItemMeta().isUnbreakable()) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Unbreakable");
return;
}
// Permissions checks on material and item types
if (!Permissions.salvageItemType(player, salvageable.getSalvageItemType())) {
NotificationManager.sendPlayerInformation(player, NotificationType.NO_PERMISSION, "mcMMO.NoPermission");
return;
}
if (!Permissions.salvageMaterialType(player, salvageable.getSalvageMaterialType())) {
NotificationManager.sendPlayerInformation(player, NotificationType.NO_PERMISSION, "mcMMO.NoPermission");
return;
}
/*int skillLevel = getSkillLevel();
int minimumSalvageableLevel = salvageable.getMinimumLevel();*/
// Level check
if (!RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE)) {
NotificationManager.sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET, "Salvage.Skills.Adept.Level", String.valueOf(RankUtils.getUnlockLevel(SubSkillType.SALVAGE_ARCANE_SALVAGE)), StringUtils.getPrettyItemString(item.getType()));
return;
}
if (item.getDurability() != 0 && (!RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_ADVANCED_SALVAGE) || !Permissions.advancedSalvage(player))) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.Adept.Damaged");
return;
}
int salvageableAmount = Salvage.calculateSalvageableAmount(item.getDurability(), salvageable.getMaximumDurability(), salvageable.getMaximumQuantity());
if (salvageableAmount == 0) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.TooDamaged");
player.sendMessage(LocaleLoader.getString("Salvage.Skills.TooDamaged"));
return;
}
salvageableAmount = Math.min(salvageableAmount, getSalvageableAmount()); // Always get at least something back, if you're capable of salvaging it.
player.getInventory().setItemInMainHand(new ItemStack(Material.AIR));
location.add(0.5, 1, 0.5);
Map<Enchantment, Integer> enchants = item.getEnchantments();
ItemStack enchantBook = null;
if (!enchants.isEmpty()) {
enchantBook = arcaneSalvageCheck(enchants);
}
ItemStack salvageResults = new ItemStack(salvageable.getSalvageMaterial(), salvageableAmount);
//Call event
if (EventUtils.callSalvageCheckEvent(player, item, salvageResults, enchantBook).isCancelled()) {
return;
}
if (enchantBook != null) {
Misc.dropItem(location, enchantBook);
}
Misc.dropItems(location, salvageResults, 1);
// BWONG BWONG BWONG - CLUNK!
if (Config.getInstance().getSalvageAnvilUseSoundsEnabled()) {
SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_BREAK);
//player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1.0F, 1.0F);
}
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Salvage.Skills.Success");
}
/*public double getMaxSalvagePercentage() {
return Math.min((((Salvage.salvageMaxPercentage / Salvage.salvageMaxPercentageLevel) * getSkillLevel()) / 100.0D), Salvage.salvageMaxPercentage / 100.0D);
}*/
public int getSalvageableAmount() {
return (RankUtils.getRank(getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE) * 1);
}
/**
* Gets the Arcane Salvage rank
*
* @return the current Arcane Salvage rank
*/
public int getArcaneSalvageRank() {
return RankUtils.getRank(getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE);
}
/*public double getExtractFullEnchantChance() {
int skillLevel = getSkillLevel();
for (Tier tier : Tier.values()) {
if (skillLevel >= tier.getLevel()) {
return tier.getExtractFullEnchantChance();
}
}
return 0;
}
public double getExtractPartialEnchantChance() {
int skillLevel = getSkillLevel();
for (Tier tier : Tier.values()) {
if (skillLevel >= tier.getLevel()) {
return tier.getExtractPartialEnchantChance();
}
}
return 0;
}*/
public double getExtractFullEnchantChance() {
return AdvancedConfig.getInstance().getArcaneSalvageExtractFullEnchantsChance(getArcaneSalvageRank());
}
public double getExtractPartialEnchantChance() {
return AdvancedConfig.getInstance().getArcaneSalvageExtractPartialEnchantsChance(getArcaneSalvageRank());
}
private ItemStack arcaneSalvageCheck(Map<Enchantment, Integer> enchants) {
Player player = getPlayer();
if (!RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE) || !Permissions.arcaneSalvage(player)) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.ArcaneFailed");
return null;
}
ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta();
boolean downgraded = false;
boolean arcaneFailure = false;
for (Entry<Enchantment, Integer> enchant : enchants.entrySet()) {
if (!Salvage.arcaneSalvageEnchantLoss
|| RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractFullEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
enchantMeta.addStoredEnchant(enchant.getKey(), enchant.getValue(), true);
}
else if (enchant.getValue() > 1
&& Salvage.arcaneSalvageDowngrades
&& RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractPartialEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
enchantMeta.addStoredEnchant(enchant.getKey(), enchant.getValue() - 1, true);
downgraded = true;
}
else {
arcaneFailure = true;
downgraded = true;
}
}
if(!arcaneFailure)
{
Map<Enchantment, Integer> newEnchants = enchantMeta.getStoredEnchants();
if (downgraded || newEnchants.size() < enchants.size()) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.ArcanePartial");
}
else {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.ArcanePartial");
}
book.setItemMeta(enchantMeta);
} else {
if(enchantMeta.getStoredEnchants().size() > 0)
{
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.ArcaneFailed");
}
return null;
}
return book;
}
/**
* Check if the player has tried to use an Anvil before.
* @param actualize
*
* @return true if the player has confirmed using an Anvil
*/
public boolean checkConfirmation(boolean actualize) {
Player player = getPlayer();
long lastUse = getLastAnvilUse();
if (!SkillUtils.cooldownExpired(lastUse, 3) || !Config.getInstance().getSalvageConfirmRequired()) {
return true;
}
if (!actualize) {
return false;
}
actualizeLastAnvilUse();
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Skills.ConfirmOrCancel", LocaleLoader.getString("Salvage.Pretty.Name"));
return false;
}
/*
* Salvage Anvil Placement
*/
public boolean getPlacedAnvil() {
return placedAnvil;
}
public void togglePlacedAnvil() {
placedAnvil = !placedAnvil;
}
/*
* Salvage Anvil Usage
*/
public int getLastAnvilUse() {
return lastClick;
}
public void setLastAnvilUse(int value) {
lastClick = value;
}
public void actualizeLastAnvilUse() {
lastClick = (int) (System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR);
}
}

View File

@ -0,0 +1,81 @@
package com.gmail.nossr50.core.skills.child.salvage.salvageables;
import com.gmail.nossr50.core.skills.ItemType;
import com.gmail.nossr50.core.skills.MaterialType;
import org.bukkit.Material;
public interface Salvageable {
/**
* Gets the type of this salvageable item
*
* @return the type of this salvageable
*/
public Material getItemMaterial();
/**
* Gets the material of the items dropped when salvaging this item
*
* @return the material of the salvage drop
*/
public Material getSalvageMaterial();
/**
* Gets the metadata byte value of the items dropped when salvaging this item
*
* @return the byte metadata of the salvage drop
*/
public byte getSalvageMaterialMetadata();
/**
* Gets the ItemType value for this salvageable item
*
* @return the ItemType for this salvageable
*/
public ItemType getSalvageItemType();
/**
* Gets the MaterialType value for this salvageable item
*
* @return the MaterialType for this salvageable
*/
public MaterialType getSalvageMaterialType();
/**
* Gets the maximum quantity of salvage materials ignoring all other salvage bonuses
*
* This is typically set to the number of items needed to create that item, for example 5 for helmets or 2 for swords
*
* @return the maximum number of items
*/
public int getMaximumQuantity();
/**
* Gets the maximum durability of this item before it breaks
*
* @return the maximum durability
*/
public short getMaximumDurability();
/**
* Gets the base salvage durability on which to calculate bonuses.
*
* This is actually the maximum durability divided by the minimum quantity
*
* @return the base salvage durability
*/
public short getBaseSalvageDurability();
/**
* Gets the minimum salvage level needed to salvage this item
*
* @return the minimum level to salvage this item, or 0 for no minimum
*/
public int getMinimumLevel();
/**
* Gets the xpMultiplier for this salvageable
*
* @return the xpMultiplier of this salvageable
*/
public double getXpMultiplier();
}

View File

@ -0,0 +1,16 @@
package com.gmail.nossr50.core.skills.child.salvage.salvageables;
import com.gmail.nossr50.core.skills.ItemType;
import com.gmail.nossr50.core.skills.MaterialType;
import org.bukkit.Material;
public class SalvageableFactory {
public static Salvageable getSalvageable(Material itemMaterial, Material repairMaterial, byte repairMetadata, int maximumQuantity, short maximumDurability) {
return getSalvageable(itemMaterial, repairMaterial, repairMetadata, 0, maximumQuantity, maximumDurability, ItemType.OTHER, MaterialType.OTHER, 1);
}
public static Salvageable getSalvageable(Material itemMaterial, Material repairMaterial, byte repairMetadata, int minimumLevel, int maximumQuantity, short maximumDurability, ItemType repairItemType, MaterialType repairMaterialType, double xpMultiplier) {
// TODO: Add in loading from config what type of repairable we want.
return new SimpleSalvageable(itemMaterial, repairMaterial, repairMetadata, minimumLevel, maximumQuantity, maximumDurability, repairItemType, repairMaterialType, xpMultiplier);
}
}

View File

@ -0,0 +1,49 @@
package com.gmail.nossr50.core.skills.child.salvage.salvageables;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public interface SalvageableManager {
/**
* Register a salvageable with the SalvageManager
*
* @param salvageable Salvageable to register
*/
public void registerSalvageable(Salvageable salvageable);
/**
* Register a list of salvageables with the SalvageManager
*
* @param salvageables List<Salvageable> to register
*/
public void registerSalvageables(List<Salvageable> salvageables);
/**
* Checks if an item is salvageable
*
* @param type Material to check if salvageable
*
* @return true if salvageable, false if not
*/
public boolean isSalvageable(Material type);
/**
* Checks if an item is salvageable
*
* @param itemStack Item to check if salvageable
*
* @return true if salvageable, false if not
*/
public boolean isSalvageable(ItemStack itemStack);
/**
* Gets the salvageable with this type
*
* @param type Material of the salvageable to look for
*
* @return the salvageable, can be null
*/
public Salvageable getSalvageable(Material type);
}

View File

@ -0,0 +1,79 @@
package com.gmail.nossr50.core.skills.child.salvage.salvageables;
import com.gmail.nossr50.core.skills.ItemType;
import com.gmail.nossr50.core.skills.MaterialType;
import org.bukkit.Material;
public class SimpleSalvageable implements Salvageable {
private final Material itemMaterial, salvageMaterial;
private final int maximumQuantity, minimumLevel;
private final short maximumDurability, baseSalvageDurability;
private final byte salvageMetadata;
private final ItemType salvageItemType;
private final MaterialType salvageMaterialType;
private final double xpMultiplier;
protected SimpleSalvageable(Material type, Material salvageMaterial, byte salvageMetadata, int minimumLevel, int maximumQuantity, short maximumDurability, ItemType salvageItemType, MaterialType salvageMaterialType, double xpMultiplier) {
this.itemMaterial = type;
this.salvageMaterial = salvageMaterial;
this.salvageMetadata = salvageMetadata;
this.salvageItemType = salvageItemType;
this.salvageMaterialType = salvageMaterialType;
this.minimumLevel = minimumLevel;
this.maximumQuantity = maximumQuantity;
this.maximumDurability = maximumDurability;
this.baseSalvageDurability = (short) (maximumDurability / maximumQuantity);
this.xpMultiplier = xpMultiplier;
}
@Override
public Material getItemMaterial() {
return itemMaterial;
}
@Override
public Material getSalvageMaterial() {
return salvageMaterial;
}
@Override
public byte getSalvageMaterialMetadata() {
return salvageMetadata;
}
@Override
public ItemType getSalvageItemType() {
return salvageItemType;
}
@Override
public MaterialType getSalvageMaterialType() {
return salvageMaterialType;
}
@Override
public int getMaximumQuantity() {
return maximumQuantity;
}
@Override
public short getMaximumDurability() {
return maximumDurability;
}
@Override
public short getBaseSalvageDurability() {
return baseSalvageDurability;
}
@Override
public int getMinimumLevel() {
return minimumLevel;
}
@Override
public double getXpMultiplier() {
return xpMultiplier;
}
}

View File

@ -0,0 +1,48 @@
package com.gmail.nossr50.core.skills.child.salvage.salvageables;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.List;
public class SimpleSalvageableManager implements SalvageableManager {
private HashMap<Material, Salvageable> salvageables;
public SimpleSalvageableManager() {
this(55);
}
public SimpleSalvageableManager(int salvageablesSize) {
this.salvageables = new HashMap<Material, Salvageable>(salvageablesSize);
}
@Override
public void registerSalvageable(Salvageable salvageable) {
Material item = salvageable.getItemMaterial();
salvageables.put(item, salvageable);
}
@Override
public void registerSalvageables(List<Salvageable> salvageables) {
for (Salvageable salvageable : salvageables) {
registerSalvageable(salvageable);
}
}
@Override
public boolean isSalvageable(Material type) {
return salvageables.containsKey(type);
}
@Override
public boolean isSalvageable(ItemStack itemStack) {
return isSalvageable(itemStack.getType());
}
@Override
public Salvageable getSalvageable(Material type) {
return salvageables.get(type);
}
}

View File

@ -0,0 +1,28 @@
package com.gmail.nossr50.core.skills.child.smelting;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class Smelting {
public static int getRank(Player player)
{
return RankUtils.getRank(player, SubSkillType.SMELTING_UNDERSTANDING_THE_ART);
}
public static int burnModifierMaxLevel = AdvancedConfig.getInstance().getBurnModifierMaxLevel();
public static double burnTimeMultiplier = AdvancedConfig.getInstance().getBurnTimeMultiplier();
public static int fluxMiningUnlockLevel = RankUtils.getUnlockLevel(SubSkillType.SMELTING_FLUX_MINING);
public static double fluxMiningChance = AdvancedConfig.getInstance().getFluxMiningChance();
protected static int getResourceXp(ItemStack smelting) {
return mcMMO.getModManager().isCustomOre(smelting.getType()) ? mcMMO.getModManager().getBlock(smelting.getType()).getSmeltingXpGain() : ExperienceConfig.getInstance().getXp(PrimarySkillType.SMELTING, smelting.getType());
}
}

View File

@ -0,0 +1,135 @@
package com.gmail.nossr50.core.skills.child.smelting;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.core.skills.primary.mining.Mining;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.inventory.ItemStack;
public class SmeltingManager extends SkillManager {
public SmeltingManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.SMELTING);
}
public boolean canUseFluxMining(BlockState blockState) {
return getSkillLevel() >= Smelting.fluxMiningUnlockLevel
&& BlockUtils.affectedByFluxMining(blockState)
&& Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.SMELTING_FLUX_MINING)
&& !mcMMO.getPlaceStore().isTrue(blockState);
}
public boolean isSecondSmeltSuccessful() {
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.SMELTING_SECOND_SMELT)
&& RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SMELTING_SECOND_SMELT, getPlayer());
}
/**
* Process the Flux Mining ability.
*
* @param blockState The {@link BlockState} to check ability activation for
* @return true if the ability was successful, false otherwise
*/
public boolean processFluxMining(BlockState blockState) {
Player player = getPlayer();
if (RandomChanceUtil.checkRandomChanceExecutionSuccess(getPlayer(), SubSkillType.SMELTING_FLUX_MINING, true)) {
ItemStack item = null;
switch (blockState.getType()) {
case Material.IRON_ORE:
item = new ItemStack(Material.IRON_INGOT);
break;
case Material.GOLD_ORE:
item = new ItemStack(Material.GOLD_INGOT);
break;
default:
break;
}
if (item == null) {
return false;
}
if (!EventUtils.simulateBlockBreak(blockState.getBlock(), player, true)) {
return false;
}
// We need to distribute Mining XP here, because the block break event gets cancelled
applyXpGain(Mining.getBlockXp(blockState), XPGainReason.PVE, XPGainSource.PASSIVE);
SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), Config.getInstance().getAbilityToolDamage());
Misc.dropItems(Misc.getBlockCenter(blockState), item, isSecondSmeltSuccessful() ? 2 : 1);
blockState.setType(Material.AIR);
if (Config.getInstance().getFluxPickaxeSoundEnabled()) {
SoundManager.sendSound(player, blockState.getLocation(), SoundType.FIZZ);
}
ParticleEffectUtils.playFluxEffect(blockState.getLocation());
return true;
}
return false;
}
/**
* Increases burn time for furnace fuel.
*
* @param burnTime The initial burn time from the {@link FurnaceBurnEvent}
*/
public int fuelEfficiency(int burnTime) {
double burnModifier = 1 + (((double) getSkillLevel() / Smelting.burnModifierMaxLevel) * Smelting.burnTimeMultiplier);
return (int) (burnTime * burnModifier);
}
public ItemStack smeltProcessing(ItemStack smelting, ItemStack result) {
applyXpGain(Smelting.getResourceXp(smelting), XPGainReason.PVE, XPGainSource.PASSIVE);
if (isSecondSmeltSuccessful()) {
ItemStack newResult = result.clone();
newResult.setAmount(result.getAmount() + 1);
return newResult;
}
return result;
}
public int vanillaXPBoost(int experience) {
return experience * getVanillaXpMultiplier();
}
/**
* Gets the vanilla XP multiplier
*
* @return the vanilla XP multiplier
*/
public int getVanillaXpMultiplier() {
return RankUtils.getRank(getPlayer(), SubSkillType.SMELTING_UNDERSTANDING_THE_ART);
}
}

View File

@ -1,6 +1,6 @@
package com.gmail.nossr50.core.datatypes.skills.interfaces;
package com.gmail.nossr50.core.skills.interfaces;
import com.gmail.nossr50.core.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.PrimarySkillType;
public interface ChildSkill extends Skill {
/**

View File

@ -1,6 +1,6 @@
package com.gmail.nossr50.core.datatypes.skills.interfaces;
package com.gmail.nossr50.core.skills.interfaces;
import com.gmail.nossr50.core.datatypes.skills.SubSkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
/**
* This interface is mostly here to maintain backwards compatibility with other mcMMO plugins

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills.interfaces;
package com.gmail.nossr50.core.skills.interfaces;
/**
* Localized interface represents skills which have localizations

View File

@ -1,6 +1,6 @@
package com.gmail.nossr50.core.datatypes.skills.progression;
package com.gmail.nossr50.core.skills.interfaces;
import com.gmail.nossr50.core.datatypes.skills.subskills.interfaces.InteractType;
import com.gmail.nossr50.core.skills.subskills.interfaces.InteractType;
import org.bukkit.event.Event;
public interface Progression {

View File

@ -1,6 +1,6 @@
package com.gmail.nossr50.core.datatypes.skills.interfaces;
package com.gmail.nossr50.core.skills.interfaces;
import com.gmail.nossr50.core.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.PrimarySkillType;
public interface Skill {
/**

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills.interfaces;
package com.gmail.nossr50.core.skills.interfaces;
import org.bukkit.inventory.ItemStack;

View File

@ -0,0 +1,17 @@
package com.gmail.nossr50.core.skills.primary.acrobatics;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
public final class Acrobatics {
public static double dodgeDamageModifier = AdvancedConfig.getInstance().getDodgeDamageModifier();
public static int dodgeXpModifier = ExperienceConfig.getInstance().getDodgeXPModifier();
public static boolean dodgeLightningDisabled = Config.getInstance().getDodgeLightningDisabled();
private Acrobatics() {}
protected static double calculateModifiedDodgeDamage(double damage, double damageModifier) {
return Math.max(damage / damageModifier, 1.0);
}
}

View File

@ -0,0 +1,73 @@
package com.gmail.nossr50.core.skills.primary.acrobatics;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LightningStrike;
import org.bukkit.entity.Player;
public class AcrobaticsManager extends SkillManager {
public AcrobaticsManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.ACROBATICS);
}
public boolean canDodge(Entity damager) {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.ACROBATICS_DODGE))
return false;
if (Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.ACROBATICS_DODGE)) {
if (damager instanceof LightningStrike && Acrobatics.dodgeLightningDisabled) {
return false;
}
return skill.shouldProcess(damager);
}
return false;
}
/**
* Handle the damage reduction and XP gain from the Dodge ability
*
* @param damage The amount of damage initially dealt by the event
* @return the modified event damage if the ability was successful, the original event damage otherwise
*/
public double dodgeCheck(double damage) {
double modifiedDamage = Acrobatics.calculateModifiedDodgeDamage(damage, Acrobatics.dodgeDamageModifier);
Player player = getPlayer();
if (!isFatal(modifiedDamage) && RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ACROBATICS_DODGE, player)) {
ParticleEffectUtils.playDodgeEffect(player);
if (mcMMOPlayer.useChatNotifications()) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Combat.Proc");
}
//Check respawn to prevent abuse
if (SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {
applyXpGain((float) (damage * Acrobatics.dodgeXpModifier), XPGainReason.PVP);
}
return modifiedDamage;
}
return damage;
}
private boolean isFatal(double damage) {
return getPlayer().getHealth() - damage <= 0;
}
}

View File

@ -0,0 +1,75 @@
package com.gmail.nossr50.core.skills.primary.alchemy;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.skills.AlchemyBrewTask;
import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.Location;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class Alchemy {
/*public enum Tier {
EIGHT(8),
SEVEN(7),
SIX(6),
FIVE(5),
FOUR(4),
THREE(3),
TWO(2),
ONE(1);
int numerical;
private Tier(int numerical) {
this.numerical = numerical;
}
public int toNumerical() {
return numerical;
}
public static Tier fromNumerical(int numerical) {
for (Tier tier : Tier.values()) {
if (tier.toNumerical() == numerical) {
return tier;
}
}
return null;
}
protected int getLevel() {
return AdvancedConfig.getInstance().getConcoctionsTierLevel(this);
}
}*/
public static final int INGREDIENT_SLOT = 3;
public static int catalysisUnlockLevel = RankUtils.getUnlockLevel(SubSkillType.ALCHEMY_CATALYSIS);
public static int catalysisMaxBonusLevel = AdvancedConfig.getInstance().getCatalysisMaxBonusLevel();
public static double catalysisMinSpeed = AdvancedConfig.getInstance().getCatalysisMinSpeed();
public static double catalysisMaxSpeed = AdvancedConfig.getInstance().getCatalysisMaxSpeed();
public static Map<Location, AlchemyBrewTask> brewingStandMap = new HashMap<Location, AlchemyBrewTask>();
private Alchemy() {}
/**
* Finish all active brews. Used upon Disable to prevent vanilla potions from being brewed upon next Enable.
*/
public static void finishAllBrews() {
mcMMO.p.debug("Completing " + brewingStandMap.size() + " unfinished Alchemy brews.");
List<AlchemyBrewTask> toFinish = new ArrayList<AlchemyBrewTask>();
toFinish.addAll(brewingStandMap.values());
for (AlchemyBrewTask alchemyBrewTask : toFinish) {
alchemyBrewTask.finishImmediately();
}
}
}

View File

@ -0,0 +1,58 @@
package com.gmail.nossr50.core.skills.primary.alchemy;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.PotionStage;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class AlchemyManager extends SkillManager {
private final double LUCKY_MODIFIER = 4.0 / 3.0;
public AlchemyManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.ALCHEMY);
}
public int getTier() {
return RankUtils.getRank(getPlayer(), SubSkillType.ALCHEMY_CONCOCTIONS);
}
public List<ItemStack> getIngredients() {
return PotionConfig.getInstance().getIngredients(getTier());
}
public String getIngredientList() {
StringBuilder list = new StringBuilder();
for (ItemStack ingredient : getIngredients()) {
String string = StringUtils.getPrettyItemString(ingredient.getType());
list.append(", ").append(string);
}
return list.substring(2);
}
public double calculateBrewSpeed(boolean isLucky) {
int skillLevel = getSkillLevel();
if (skillLevel < Alchemy.catalysisUnlockLevel) {
return Alchemy.catalysisMinSpeed;
}
return Math.min(Alchemy.catalysisMaxSpeed, Alchemy.catalysisMinSpeed + (Alchemy.catalysisMaxSpeed - Alchemy.catalysisMinSpeed) * (skillLevel - Alchemy.catalysisUnlockLevel) / (Alchemy.catalysisMaxBonusLevel - Alchemy.catalysisUnlockLevel)) * (isLucky ? LUCKY_MODIFIER : 1.0);
}
public void handlePotionBrewSuccesses(PotionStage potionStage, int amount) {
applyXpGain((float) (ExperienceConfig.getInstance().getPotionXP(potionStage) * amount), XPGainReason.PVE, XPGainSource.PASSIVE);
}
}

View File

@ -1,4 +1,4 @@
package com.gmail.nossr50.core.datatypes.skills.alchemy;
package com.gmail.nossr50.core.skills.primary.alchemy;
import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
import org.bukkit.Color;

View File

@ -0,0 +1,255 @@
package com.gmail.nossr50.core.skills.primary.alchemy;
import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.PotionStage;
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.AlchemyBrewCheckTask;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.core.data.UserManager;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.block.BrewingStand;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.BrewerInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
public final class AlchemyPotionBrewer {
public static boolean isValidBrew(Player player, ItemStack[] contents) {
if (!isValidIngredient(player, contents[Alchemy.INGREDIENT_SLOT])) {
return false;
}
for (int i = 0; i < 3; i++) {
if (contents[i] == null || contents[i].getType() != Material.POTION && contents[i].getType() != Material.SPLASH_POTION && contents[i].getType() != Material.LINGERING_POTION) {
continue;
}
if (getChildPotion(PotionConfig.getInstance().getPotion(contents[i]), contents[Alchemy.INGREDIENT_SLOT]) != null) {
return true;
}
}
return false;
}
private static AlchemyPotion getChildPotion(AlchemyPotion potion, ItemStack ingredient) {
if (potion != null) {
return potion.getChild(ingredient);
}
return null;
}
public static boolean isEmpty(ItemStack item) {
return item == null || item.getType() == Material.AIR || item.getAmount() == 0;
}
private static void removeIngredient(BrewerInventory inventory, Player player) {
ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone();
if (isEmpty(ingredient) || !isValidIngredient(player, ingredient)) {
return;
}
else if (ingredient.getAmount() <= 1) {
inventory.setIngredient(null);
return;
}
else {
ingredient.setAmount(ingredient.getAmount() - 1);
inventory.setIngredient(ingredient);
return;
}
}
private static boolean hasIngredient(BrewerInventory inventory, Player player) {
ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone();
return !isEmpty(ingredient) && isValidIngredient(player, ingredient);
}
public static boolean isValidIngredient(Player player, ItemStack item) {
if (isEmpty(item)) {
return false;
}
for (ItemStack ingredient : getValidIngredients(player)) {
if (item.isSimilar(ingredient)) {
return true;
}
}
return false;
}
private static List<ItemStack> getValidIngredients(Player player) {
return PotionConfig.getInstance().getIngredients((player == null || !Permissions.isSubSkillEnabled(player, SubSkillType.ALCHEMY_CONCOCTIONS)) ? 1 : UserManager.getPlayer(player).getAlchemyManager().getTier());
}
public static void finishBrewing(BlockState brewingStand, Player player, boolean forced) {
if (!(brewingStand instanceof BrewingStand)) {
return;
}
BrewerInventory inventory = ((BrewingStand) brewingStand).getInventory();
ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone();
if (!hasIngredient(inventory, player)) {
return;
}
List<AlchemyPotion> inputList = new ArrayList<AlchemyPotion>();
for (int i = 0; i < 3; i++) {
ItemStack item = inventory.getItem(i);
if (isEmpty(item) || item.getType() == Material.GLASS_BOTTLE || !PotionConfig.getInstance().isValidPotion(item)) {
continue;
}
AlchemyPotion input = PotionConfig.getInstance().getPotion(item);
AlchemyPotion output = input.getChild(ingredient);
inputList.add(input);
if (output != null) {
inventory.setItem(i, output.toItemStack(item.getAmount()).clone());
}
}
FakeBrewEvent event = new FakeBrewEvent(brewingStand.getBlock(), inventory, ((BrewingStand) brewingStand).getFuelLevel());
mcMMO.p.getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || inputList.isEmpty()) {
return;
}
removeIngredient(inventory, player);
for (AlchemyPotion input : inputList) {
AlchemyPotion output = input.getChild(ingredient);
if (output != null && player != null) {
PotionStage potionStage = PotionStage.getPotionStage(input, output);
if (UserManager.hasPlayerDataKey(player)) {
UserManager.getPlayer(player).getAlchemyManager().handlePotionBrewSuccesses(potionStage, 1);
}
}
}
if (!forced) {
scheduleUpdate(inventory);
}
}
public static boolean transferItems(InventoryView view, int fromSlot, ClickType click) {
boolean success = false;
if (click.isLeftClick()) {
success = transferItems(view, fromSlot);
}
else if (click.isRightClick()) {
success = transferOneItem(view, fromSlot);
}
return success;
}
private static boolean transferOneItem(InventoryView view, int fromSlot) {
ItemStack from = view.getItem(fromSlot).clone();
ItemStack to = view.getItem(Alchemy.INGREDIENT_SLOT).clone();
if (isEmpty(from)) {
return false;
}
boolean emptyTo = isEmpty(to);
int fromAmount = from.getAmount();
if (!emptyTo && fromAmount >= from.getType().getMaxStackSize()) {
return false;
}
else if (emptyTo || from.isSimilar(to)) {
if (emptyTo) {
to = from.clone();
to.setAmount(1);
}
else {
to.setAmount(to.getAmount() + 1);
}
from.setAmount(fromAmount - 1);
view.setItem(Alchemy.INGREDIENT_SLOT, to);
view.setItem(fromSlot, from);
return true;
}
return false;
}
/**
* Transfer items between two ItemStacks, returning the leftover status
*/
private static boolean transferItems(InventoryView view, int fromSlot) {
ItemStack from = view.getItem(fromSlot).clone();
ItemStack to = view.getItem(Alchemy.INGREDIENT_SLOT).clone();
if (isEmpty(from)) {
return false;
}
else if (isEmpty(to)) {
view.setItem(Alchemy.INGREDIENT_SLOT, from);
view.setItem(fromSlot, null);
return true;
}
else if (from.isSimilar(to)) {
int fromAmount = from.getAmount();
int toAmount = to.getAmount();
int maxSize = to.getType().getMaxStackSize();
if (fromAmount + toAmount > maxSize) {
int left = fromAmount + toAmount - maxSize;
to.setAmount(maxSize);
view.setItem(Alchemy.INGREDIENT_SLOT, to);
from.setAmount(left);
view.setItem(fromSlot, from);
return true;
}
to.setAmount(fromAmount + toAmount);
view.setItem(fromSlot, null);
view.setItem(Alchemy.INGREDIENT_SLOT, to);
return true;
}
return false;
}
public static void scheduleCheck(Player player, BrewingStand brewingStand) {
new AlchemyBrewCheckTask(player, brewingStand).runTask(mcMMO.p);
}
public static void scheduleUpdate(Inventory inventory) {
for (HumanEntity humanEntity : inventory.getViewers()) {
if (humanEntity instanceof Player) {
new PlayerUpdateInventoryTask((Player) humanEntity).runTask(mcMMO.p);
}
}
}
}

View File

@ -0,0 +1,75 @@
package com.gmail.nossr50.core.skills.primary.archery;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Archery {
private static List<TrackedEntity> trackedEntities = new ArrayList<TrackedEntity>();
public static double skillShotMaxBonusDamage = AdvancedConfig.getInstance().getSkillShotDamageMax();
public static double dazeBonusDamage = AdvancedConfig.getInstance().getDazeBonusDamage();
public static final double DISTANCE_XP_MULTIPLIER = ExperienceConfig.getInstance().getArcheryDistanceMultiplier();
protected static void incrementTrackerValue(LivingEntity livingEntity) {
for (TrackedEntity trackedEntity : trackedEntities) {
if (trackedEntity.getLivingEntity().getEntityId() == livingEntity.getEntityId()) {
trackedEntity.incrementArrowCount();
return;
}
}
addToTracker(livingEntity); // If the entity isn't tracked yet
}
protected static void addToTracker(LivingEntity livingEntity) {
TrackedEntity trackedEntity = new TrackedEntity(livingEntity);
trackedEntity.incrementArrowCount();
trackedEntities.add(trackedEntity);
}
protected static void removeFromTracker(TrackedEntity trackedEntity) {
trackedEntities.remove(trackedEntity);
}
/**
* Check for arrow retrieval.
*
* @param livingEntity The entity hit by the arrows
*/
public static void arrowRetrievalCheck(LivingEntity livingEntity) {
for (Iterator<TrackedEntity> entityIterator = trackedEntities.iterator(); entityIterator.hasNext();) {
TrackedEntity trackedEntity = entityIterator.next();
if (trackedEntity.getID() == livingEntity.getUniqueId()) {
Misc.dropItems(livingEntity.getLocation(), new ItemStack(Material.ARROW), trackedEntity.getArrowCount());
entityIterator.remove();
return;
}
}
}
public static double getSkillShotBonusDamage(Player player, double oldDamage)
{
double damageBonusPercent = getDamageBonusPercent(player);
double newDamage = oldDamage + (oldDamage * damageBonusPercent);
return Math.min(newDamage, Archery.skillShotMaxBonusDamage);
}
public static double getDamageBonusPercent(Player player) {
return ((RankUtils.getRank(player, SubSkillType.ARCHERY_SKILL_SHOT)) * AdvancedConfig.getInstance().getSkillShotRankDamageMultiplier()) / 100.0D;
}
}

View File

@ -0,0 +1,116 @@
package com.gmail.nossr50.core.skills.primary.archery;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.core.data.UserManager;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
public class ArcheryManager extends SkillManager {
public ArcheryManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.ARCHERY);
}
public boolean canDaze(LivingEntity target) {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.ARCHERY_DAZE))
return false;
return target instanceof Player && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.ARCHERY_DAZE);
}
public boolean canSkillShot() {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.ARCHERY_SKILL_SHOT))
return false;
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.ARCHERY_SKILL_SHOT);
}
public boolean canRetrieveArrows() {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.ARCHERY_ARROW_RETRIEVAL))
return false;
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.ARCHERY_ARROW_RETRIEVAL);
}
/**
* Calculate bonus XP awarded for Archery when hitting a far-away target.
*
* @param target The {@link LivingEntity} damaged by the arrow
* @param damager The {@link Entity} who shot the arrow
*/
public double distanceXpBonusMultiplier(LivingEntity target, Entity damager) {
Location firedLocation = (Location) damager.getMetadata(mcMMO.arrowDistanceKey).get(0).value();
Location targetLocation = target.getLocation();
if (firedLocation.getWorld() != targetLocation.getWorld()) {
return 1;
}
return 1 + Math.min(firedLocation.distance(targetLocation), 50) * Archery.DISTANCE_XP_MULTIPLIER;
}
/**
* Track arrows fired for later retrieval.
*
* @param target The {@link LivingEntity} damaged by the arrow
*/
public void retrieveArrows(LivingEntity target) {
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ARCHERY_ARROW_RETRIEVAL, getPlayer())) {
Archery.incrementTrackerValue(target);
}
}
/**
* Handle the effects of the Daze ability
*
* @param defender The {@link Player} being affected by the ability
*/
public double daze(Player defender) {
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ARCHERY_DAZE, getPlayer())) {
return 0;
}
Location dazedLocation = defender.getLocation();
dazedLocation.setPitch(90 - Misc.getRandom().nextInt(181));
defender.teleport(dazedLocation);
defender.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, 20 * 10, 10));
if (UserManager.getPlayer(defender).useChatNotifications()) {
NotificationManager.sendPlayerInformation(defender, NotificationType.SUBSKILL_MESSAGE, "Combat.TouchedFuzzy");
}
if (mcMMOPlayer.useChatNotifications()) {
NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Combat.TargetDazed");
}
return Archery.dazeBonusDamage;
}
/**
* Calculates the damage to deal after Skill Shot has been applied
*
* @param oldDamage The raw damage value of this arrow before we modify it
*/
public double skillShot(double oldDamage) {
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.ARCHERY_SKILL_SHOT, getPlayer())) {
return oldDamage;
}
return Archery.getSkillShotBonusDamage(getPlayer(), oldDamage);
}
}

View File

@ -0,0 +1,44 @@
package com.gmail.nossr50.core.skills.primary.archery;
import com.gmail.nossr50.mcMMO;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID;
public class TrackedEntity extends BukkitRunnable {
private LivingEntity livingEntity;
private UUID id;
private int arrowCount;
protected TrackedEntity(LivingEntity livingEntity) {
this.livingEntity = livingEntity;
this.id = livingEntity.getUniqueId();
this.runTaskTimer(mcMMO.p, 12000, 12000);
}
@Override
public void run() {
if (!livingEntity.isValid()) {
Archery.removeFromTracker(this);
this.cancel();
}
}
protected LivingEntity getLivingEntity() {
return livingEntity;
}
protected UUID getID() {
return id;
}
protected int getArrowCount() {
return arrowCount;
}
protected void incrementArrowCount() {
arrowCount++;
}
}

View File

@ -0,0 +1,46 @@
package com.gmail.nossr50.core.skills.primary.axes;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class Axes {
public static double axeMasteryRankDamageMultiplier = AdvancedConfig.getInstance().getAxeMasteryRankDamageMultiplier();
public static double criticalHitPVPModifier = AdvancedConfig.getInstance().getCriticalStrikesPVPModifier();
public static double criticalHitPVEModifier = AdvancedConfig.getInstance().getCriticalStrikesPVEModifier();
public static int impactIncreaseLevel = AdvancedConfig.getInstance().getArmorImpactIncreaseLevel();
public static double impactChance = AdvancedConfig.getInstance().getImpactChance();
public static double impactMaxDurabilityModifier = AdvancedConfig.getInstance().getArmorImpactMaxDurabilityDamage() / 100D;
public static double greaterImpactBonusDamage = AdvancedConfig.getInstance().getGreaterImpactBonusDamage();
public static double greaterImpactChance = AdvancedConfig.getInstance().getGreaterImpactChance();
public static double greaterImpactKnockbackMultiplier = AdvancedConfig.getInstance().getGreaterImpactModifier();
public static double skullSplitterModifier = AdvancedConfig.getInstance().getSkullSplitterModifier();
protected static boolean hasArmor(LivingEntity target) {
for (ItemStack itemStack : target.getEquipment().getArmorContents()) {
if (itemStack != null && ItemUtils.isArmor(itemStack)) {
return true;
}
}
return false;
}
/**
* For every rank in Axe Mastery we add RankDamageMultiplier to get the total bonus damage from Axe Mastery
* @param player The target player
* @return The axe mastery bonus damage which will be added to their attack
*/
public static double getAxeMasteryBonusDamage(Player player)
{
return RankUtils.getRank(player, SubSkillType.AXES_AXE_MASTERY) * Axes.axeMasteryRankDamageMultiplier;
}
}

View File

@ -0,0 +1,171 @@
package com.gmail.nossr50.core.skills.primary.axes;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.SuperAbilityType;
import com.gmail.nossr50.core.skills.ToolType;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.core.data.UserManager;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
public class AxesManager extends SkillManager {
public AxesManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.AXES);
}
public boolean canUseAxeMastery() {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_AXE_MASTERY))
return false;
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_AXE_MASTERY);
}
public boolean canCriticalHit(LivingEntity target) {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_CRITICAL_STRIKES))
return false;
return target.isValid() && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_CRITICAL_STRIKES);
}
public boolean canImpact(LivingEntity target) {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_ARMOR_IMPACT))
return false;
return target.isValid() && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_ARMOR_IMPACT) && Axes.hasArmor(target);
}
public boolean canGreaterImpact(LivingEntity target) {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_GREATER_IMPACT))
return false;
return target.isValid() && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.AXES_GREATER_IMPACT) && !Axes.hasArmor(target);
}
public boolean canUseSkullSplitter(LivingEntity target) {
if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.AXES_SKULL_SPLITTER))
return false;
return target.isValid() && mcMMOPlayer.getAbilityMode(SuperAbilityType.SKULL_SPLITTER) && Permissions.skullSplitter(getPlayer());
}
public boolean canActivateAbility() {
return mcMMOPlayer.getToolPreparationMode(ToolType.AXE) && Permissions.skullSplitter(getPlayer());
}
/**
* Handle the effects of the Axe Mastery ability
*/
public double axeMastery() {
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.AXES_AXE_MASTERY, getPlayer())) {
return 0;
}
return Axes.getAxeMasteryBonusDamage(getPlayer());
}
/**
* Handle the effects of the Critical Hit ability
*
* @param target The {@link LivingEntity} being affected by the ability
* @param damage The amount of damage initially dealt by the event
*/
public double criticalHit(LivingEntity target, double damage) {
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.AXES_CRITICAL_STRIKES, getPlayer())) {
return 0;
}
Player player = getPlayer();
if (mcMMOPlayer.useChatNotifications()) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Axes.Combat.CriticalHit");
}
if (target instanceof Player) {
Player defender = (Player) target;
if (UserManager.getPlayer(defender).useChatNotifications()) {
NotificationManager.sendPlayerInformation(defender, NotificationType.SUBSKILL_MESSAGE, "Axes.Combat.CritStruck");
}
damage = (damage * Axes.criticalHitPVPModifier) - damage;
}
else {
damage = (damage * Axes.criticalHitPVEModifier) - damage;
}
return damage;
}
/**
* Handle the effects of the Impact ability
*
* @param target The {@link LivingEntity} being affected by Impact
*/
public void impactCheck(LivingEntity target) {
int durabilityDamage = getImpactDurabilityDamage();
for (ItemStack armor : target.getEquipment().getArmorContents()) {
if (armor != null && ItemUtils.isArmor(armor)) {
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_ARMOR_IMPACT, getPlayer())) {
SkillUtils.handleDurabilityChange(armor, durabilityDamage, Axes.impactMaxDurabilityModifier);
}
}
}
}
public int getImpactDurabilityDamage() {
return 1 + (getSkillLevel() / Axes.impactIncreaseLevel);
}
/**
* Handle the effects of the Greater Impact ability
*
* @param target The {@link LivingEntity} being affected by the ability
*/
public double greaterImpact(LivingEntity target) {
//static chance (3rd param)
if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_GREATER_IMPACT, getPlayer())) {
return 0;
}
Player player = getPlayer();
ParticleEffectUtils.playGreaterImpactEffect(target);
target.setVelocity(player.getLocation().getDirection().normalize().multiply(Axes.greaterImpactKnockbackMultiplier));
if (mcMMOPlayer.useChatNotifications()) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Axes.Combat.GI.Proc");
}
if (target instanceof Player) {
Player defender = (Player) target;
if (UserManager.getPlayer(defender).useChatNotifications()) {
NotificationManager.sendPlayerInformation(defender, NotificationType.SUBSKILL_MESSAGE, "Axes.Combat.GI.Struck");
}
}
return Axes.greaterImpactBonusDamage;
}
/**
* Handle the effects of the Skull Splitter ability
*
* @param target The {@link LivingEntity} being affected by the ability
* @param damage The amount of damage initially dealt by the event
*/
public void skullSplitterCheck(LivingEntity target, double damage, Map<DamageModifier, Double> modifiers) {
CombatUtils.applyAbilityAoE(getPlayer(), target, damage / Axes.skullSplitterModifier, modifiers, skill);
}
}

View File

@ -0,0 +1,37 @@
package com.gmail.nossr50.core.skills.primary.excavation;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.core.config.treasure.TreasureConfig;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.treasure.ExcavationTreasure;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.StringUtils;
import org.bukkit.block.BlockState;
import java.util.ArrayList;
import java.util.List;
public class Excavation {
/**
* Get the list of possible {@link ExcavationTreasure |ExcavationTreasures} obtained from a given block.
*
* @param blockState The {@link BlockState} of the block to check.
* @return the list of treasures that could be found
*/
protected static List<ExcavationTreasure> getTreasures(BlockState blockState) {
String friendly = StringUtils.getFriendlyConfigBlockDataString(blockState.getBlockData());
if (TreasureConfig.getInstance().excavationMap.containsKey(friendly))
return TreasureConfig.getInstance().excavationMap.get(friendly);
return new ArrayList<ExcavationTreasure>();
}
protected static int getBlockXP(BlockState blockState) {
int xp = ExperienceConfig.getInstance().getXp(PrimarySkillType.EXCAVATION, blockState.getType());
if (xp == 0 && mcMMO.getModManager().isCustomExcavationBlock(blockState)) {
xp = mcMMO.getModManager().getBlock(blockState).getXpGain();
}
return xp;
}
}

View File

@ -0,0 +1,83 @@
package com.gmail.nossr50.core.skills.primary.excavation;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.treasure.ExcavationTreasure;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Location;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import java.util.List;
public class ExcavationManager extends SkillManager {
public ExcavationManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.EXCAVATION);
}
/**
* Process treasure drops & XP gain for Excavation.
*
* @param blockState The {@link BlockState} to check ability activation for
*/
public void excavationBlockCheck(BlockState blockState) {
int xp = Excavation.getBlockXP(blockState);
if (Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.EXCAVATION_ARCHAEOLOGY)) {
List<ExcavationTreasure> treasures = Excavation.getTreasures(blockState);
if (!treasures.isEmpty()) {
int skillLevel = getSkillLevel();
Location location = Misc.getBlockCenter(blockState);
for (ExcavationTreasure treasure : treasures) {
if (skillLevel >= treasure.getDropLevel()
&& RandomChanceUtil.checkRandomChanceExecutionSuccess(getPlayer(), PrimarySkillType.EXCAVATION, treasure.getDropChance())) {
xp += treasure.getXp();
Misc.dropItem(location, treasure.getDrop());
}
}
}
}
applyXpGain(xp, XPGainReason.PVE);
}
public void printExcavationDebug(Player player, BlockState blockState)
{
if (Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.EXCAVATION_ARCHAEOLOGY)) {
List<ExcavationTreasure> treasures = Excavation.getTreasures(blockState);
if (!treasures.isEmpty()) {
for (ExcavationTreasure treasure : treasures) {
player.sendMessage("|||||||||||||||||||||||||||||||||");
player.sendMessage("[mcMMO DEBUG] Treasure found: ("+treasure.getDrop().getType().toString()+")");
player.sendMessage("[mcMMO DEBUG] Drop Chance for Treasure: "+treasure.getDropChance());
player.sendMessage("[mcMMO DEBUG] Skill Level Required: "+treasure.getDropLevel());
player.sendMessage("[mcMMO DEBUG] XP for Treasure: "+treasure.getXp());
}
} else {
player.sendMessage("[mcMMO DEBUG] No treasures found for this block.");
}
}
}
/**
* Process the Giga Drill Breaker ability.
*
* @param blockState The {@link BlockState} to check ability activation for
*/
public void gigaDrillBreaker(BlockState blockState) {
excavationBlockCheck(blockState);
excavationBlockCheck(blockState);
SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), Config.getInstance().getAbilityToolDamage());
}
}

View File

@ -0,0 +1,66 @@
package com.gmail.nossr50.core.skills.primary.fishing;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.config.treasure.TreasureConfig;
import com.gmail.nossr50.core.skills.treasure.ShakeTreasure;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.adapter.BiomeAdapter;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
public final class Fishing {
protected static final HashMap<Material, List<Enchantment>> ENCHANTABLE_CACHE = new HashMap<Material, List<Enchantment>>();
public static int fishermansDietRankLevel1 = AdvancedConfig.getInstance().getFishermanDietRankChange();
public static int fishermansDietRankLevel2 = fishermansDietRankLevel1 * 2;
public static int fishermansDietMaxLevel = fishermansDietRankLevel1 * 5;
public static Set<Biome> masterAnglerBiomes = BiomeAdapter.WATER_BIOMES;
public static Set<Biome> iceFishingBiomes = BiomeAdapter.ICE_BIOMES;
private Fishing() {}
/**
* Finds the possible drops of an entity
*
* @param target
* Targeted entity
* @return possibleDrops List of ItemStack that can be dropped
*/
protected static List<ShakeTreasure> findPossibleDrops(LivingEntity target) {
if (TreasureConfig.getInstance().shakeMap.containsKey(target.getType()))
return TreasureConfig.getInstance().shakeMap.get(target.getType());
return null;
}
/**
* Randomly chooses a drop among the list
*
* @param possibleDrops
* List of ItemStack that can be dropped
* @return Chosen ItemStack
*/
protected static ItemStack chooseDrop(List<ShakeTreasure> possibleDrops) {
int dropProbability = Misc.getRandom().nextInt(100);
double cumulatedProbability = 0;
for (ShakeTreasure treasure : possibleDrops) {
cumulatedProbability += treasure.getDropChance();
if (dropProbability < cumulatedProbability) {
return treasure.getDrop().clone();
}
}
return null;
}
}

View File

@ -0,0 +1,515 @@
package com.gmail.nossr50.core.skills.primary.fishing;
import com.gmail.nossr50.core.config.skills.AdvancedConfig;
import com.gmail.nossr50.core.config.skills.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.core.config.treasure.TreasureConfig;
import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.core.skills.PrimarySkillType;
import com.gmail.nossr50.core.skills.SubSkillType;
import com.gmail.nossr50.core.skills.treasure.EnchantmentTreasure;
import com.gmail.nossr50.core.skills.treasure.FishingTreasure;
import com.gmail.nossr50.core.skills.treasure.Rarity;
import com.gmail.nossr50.core.skills.treasure.ShakeTreasure;
import com.gmail.nossr50.core.skills.SkillManager;
import com.gmail.nossr50.events.skills.fishing.McMMOPlayerFishingTreasureEvent;
import com.gmail.nossr50.events.skills.fishing.McMMOPlayerShakeEvent;
import com.gmail.nossr50.util.*;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.util.BoundingBox;
import java.util.*;
public class FishingManager extends SkillManager {
private final long FISHING_COOLDOWN_SECONDS = 1000L;
private long fishingTimestamp = 0L;
private BoundingBox lastFishingBoundingBox;
private Item fishingCatch;
private Location hookLocation;
public FishingManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.FISHING);
}
public boolean canShake(Entity target) {
return target instanceof LivingEntity && RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_SHAKE) && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_SHAKE);
}
public boolean canMasterAngler() {
return getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER) && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER);
}
public boolean exploitPrevention(BoundingBox boundingBox) {
Block targetBlock = getPlayer().getTargetBlock(BlockUtils.getTransparentBlocks(), 100);
if (!targetBlock.isLiquid()) {
return false;
}
long currentTime = System.currentTimeMillis();
boolean hasFished = (currentTime < fishingTimestamp + (FISHING_COOLDOWN_SECONDS * 10));
if(hasFished)
fishingTimestamp = currentTime;
boolean sameTarget = (lastFishingBoundingBox != null && lastFishingBoundingBox.overlaps(boundingBox));
lastFishingBoundingBox = boundingBox;
return hasFished || sameTarget;
}
public void setFishingTarget() {
getPlayer().getTargetBlock(BlockUtils.getTransparentBlocks(), 100);
}
public boolean canIceFish(Block block) {
if (getSkillLevel() < RankUtils.getUnlockLevel(SubSkillType.FISHING_ICE_FISHING)) {
return false;
}
if (block.getType() != Material.ICE) {
return false;
}
// Make sure this is a body of water, not just a block of ice.
if (!Fishing.iceFishingBiomes.contains(block.getBiome()) && (block.getRelative(BlockFace.DOWN, 3).getType() != Material.WATER)) {
return false;
}
Player player = getPlayer();
if (!Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_ICE_FISHING)) {
return false;
}
return EventUtils.simulateBlockBreak(block, player, false);
}
/**
* Gets the loot tier
*
* @return the loot tier
*/
public int getLootTier() {
return RankUtils.getRank(getPlayer(), SubSkillType.FISHING_TREASURE_HUNTER);
}
public double getShakeChance() {
return AdvancedConfig.getInstance().getShakeChance(getLootTier());
}
protected int getVanillaXPBoostModifier() {
return AdvancedConfig.getInstance().getFishingVanillaXPModifier(getLootTier());
}
/**
* Gets the Shake Mob probability
*
* @return Shake Mob probability
*/
public double getShakeProbability() {
return getShakeChance();
}
/**
* Handle the Fisherman's Diet ability
*
* @param rankChange The # of levels to change rank for the food
* @param eventFoodLevel The initial change in hunger from the event
*
* @return the modified change in hunger for the event
*/
public int handleFishermanDiet(int rankChange, int eventFoodLevel) {
return SkillUtils.handleFoodSkills(getPlayer(), eventFoodLevel, SubSkillType.FISHING_FISHERMANS_DIET);
}
public void iceFishing(FishHook hook, Block block) {
// Make a hole
block.setType(Material.WATER);
for (int x = -1; x <= 1; x++) {
for (int z = -1; z <= 1; z++) {
Block relative = block.getRelative(x, 0, z);
if (relative.getType() == Material.ICE) {
relative.setType(Material.WATER);
}
}
}
// Recast in the new spot
EventUtils.callFakeFishEvent(getPlayer(), hook);
}
public void masterAngler(FishHook hook) {
Player player = getPlayer();
Location location = hook.getLocation();
double biteChance = hook.getBiteChance();
hookLocation = location;
if (Fishing.masterAnglerBiomes.contains(location.getBlock().getBiome())) {
biteChance = biteChance * AdvancedConfig.getInstance().getMasterAnglerBiomeModifier();
}
if (player.isInsideVehicle() && player.getVehicle().getType() == EntityType.BOAT) {
biteChance = biteChance * AdvancedConfig.getInstance().getMasterAnglerBoatModifier();
}
hook.setBiteChance(Math.min(biteChance, 1.0));
}
public boolean isMagicHunterEnabled()
{
return RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_MAGIC_HUNTER)
&& RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_TREASURE_HUNTER)
&& Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_TREASURE_HUNTER);
}
/**
* Process the results from a successful fishing trip
*
* @param fishingCatch The {@link Item} initially caught
*/
public void handleFishing(Item fishingCatch) {
this.fishingCatch = fishingCatch;
int fishXp = ExperienceConfig.getInstance().getXp(PrimarySkillType.FISHING, fishingCatch.getItemStack().getType());
int treasureXp = 0;
Player player = getPlayer();
FishingTreasure treasure = null;
if (Config.getInstance().getFishingDropsEnabled() && Permissions.isSubSkillEnabled(player, SubSkillType.FISHING_TREASURE_HUNTER)) {
treasure = getFishingTreasure();
this.fishingCatch = null;
}
if (treasure != null) {
ItemStack treasureDrop = treasure.getDrop().clone(); // Not cloning is bad, m'kay?
Map<Enchantment, Integer> enchants = new HashMap<Enchantment, Integer>();
if (isMagicHunterEnabled()
&& ItemUtils.isEnchantable(treasureDrop)) {
enchants = handleMagicHunter(treasureDrop);
}
McMMOPlayerFishingTreasureEvent event = EventUtils.callFishingTreasureEvent(player, treasureDrop, treasure.getXp(), enchants);
if (!event.isCancelled()) {
treasureDrop = event.getTreasure();
treasureXp = event.getXp();
}
else {
treasureDrop = null;
treasureXp = 0;
}
// Drop the original catch at the feet of the player and set the treasure as the real catch
if (treasureDrop != null) {
boolean enchanted = false;
if (!enchants.isEmpty()) {
treasureDrop.addUnsafeEnchantments(enchants);
enchanted = true;
}
if (enchanted) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Fishing.Ability.TH.MagicFound");
}
if (Config.getInstance().getFishingExtraFish()) {
Misc.dropItem(player.getEyeLocation(), fishingCatch.getItemStack());
}
fishingCatch.setItemStack(treasureDrop);
}
}
applyXpGain(fishXp + treasureXp, XPGainReason.PVE);
}
/**
* Handle the vanilla XP boost for Fishing
*
* @param experience The amount of experience initially awarded by the event
*
* @return the modified event damage
*/
public int handleVanillaXpBoost(int experience) {
return experience * getVanillaXpMultiplier();
}
public Location getHookLocation() {
return hookLocation;
}
/**
* Handle the Shake ability
*
* @param target The {@link LivingEntity} affected by the ability
*/
public void shakeCheck(LivingEntity target) {
if (RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getShakeChance(), getPlayer(), SubSkillType.FISHING_SHAKE))) {
List<ShakeTreasure> possibleDrops = Fishing.findPossibleDrops(target);
if (possibleDrops == null || possibleDrops.isEmpty()) {
return;
}
ItemStack drop = Fishing.chooseDrop(possibleDrops);
// It's possible that chooseDrop returns null if the sum of probability in possibleDrops is inferior than 100
if (drop == null) {
return;
}
// Extra processing depending on the mob and drop type
switch (target.getType()) {
case EntityType.PLAYER:
Player targetPlayer = (Player) target;
switch (drop.getType()) {
case Material.PLAYER_HEAD:
drop.setDurability((short) 3);
SkullMeta skullMeta = (SkullMeta) drop.getItemMeta();
skullMeta.setOwningPlayer(targetPlayer);
drop.setItemMeta(skullMeta);
break;
case Material.BEDROCK:
if (TreasureConfig.getInstance().getInventoryStealEnabled()) {
PlayerInventory inventory = targetPlayer.getInventory();
int length = inventory.getContents().length;
int slot = Misc.getRandom().nextInt(length);
drop = inventory.getItem(slot);
if (drop == null) {
break;
}
if (TreasureConfig.getInstance().getInventoryStealStacks()) {
inventory.setItem(slot, null);
}
else {
inventory.setItem(slot, (drop.getAmount() > 1) ? new ItemStack(drop.getType(), drop.getAmount() - 1) : null);
drop.setAmount(1);
}
targetPlayer.updateInventory();
}
break;
default:
break;
}
break;
case EntityType.SHEEP:
Sheep sheep = (Sheep) target;
if (drop.getType().name().endsWith("WOOL")) {
if (sheep.isSheared()) {
return;
}
sheep.setSheared(true);
}
break;
default:
break;
}
McMMOPlayerShakeEvent shakeEvent = new McMMOPlayerShakeEvent(getPlayer(), drop);
drop = shakeEvent.getDrop();
if (shakeEvent.isCancelled() || drop == null) {
return;
}
Misc.dropItem(target.getLocation(), drop);
CombatUtils.dealDamage(target, Math.max(target.getMaxHealth() / 4, 1), EntityDamageEvent.DamageCause.CUSTOM, getPlayer()); // Make it so you can shake a mob no more than 4 times.
applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE);
}
}
/**
* Process the Treasure Hunter ability for Fishing
*
* @return The {@link FishingTreasure} found, or null if no treasure was found.
*/
private FishingTreasure getFishingTreasure() {
double diceRoll = Misc.getRandom().nextDouble() * 100;
int luck;
if (getPlayer().getInventory().getItemInMainHand().getType() == Material.FISHING_ROD) {
luck = getPlayer().getInventory().getItemInMainHand().getEnchantmentLevel(Enchantment.LUCK);
}
else {
// We know something was caught, so if the rod wasn't in the main hand it must be in the offhand
luck = getPlayer().getInventory().getItemInOffHand().getEnchantmentLevel(Enchantment.LUCK);
}
// Rather than subtracting luck (and causing a minimum 3% chance for every drop), scale by luck.
diceRoll *= (1.0 - luck * Config.getInstance().getFishingLureModifier() / 100);
FishingTreasure treasure = null;
for (Rarity rarity : Rarity.values()) {
double dropRate = TreasureConfig.getInstance().getItemDropRate(getLootTier(), rarity);
if (diceRoll <= dropRate) {
/*if (rarity == Rarity.TRAP) {
handleTraps();
break;
}*/
List<FishingTreasure> fishingTreasures = TreasureConfig.getInstance().fishingRewards.get(rarity);
if (fishingTreasures.isEmpty()) {
return null;
}
treasure = fishingTreasures.get(Misc.getRandom().nextInt(fishingTreasures.size()));
break;
}
diceRoll -= dropRate;
}
if (treasure == null) {
return null;
}
ItemStack treasureDrop = treasure.getDrop().clone();
short maxDurability = treasureDrop.getType().getMaxDurability();
if (maxDurability > 0) {
treasureDrop.setDurability((short) (Misc.getRandom().nextInt(maxDurability)));
}
if (treasureDrop.getAmount() > 1) {
treasureDrop.setAmount(Misc.getRandom().nextInt(treasureDrop.getAmount()) + 1);
}
treasure.setDrop(treasureDrop);
return treasure;
}
/**
* Process the Magic Hunter ability
*
* @param treasureDrop The {@link ItemStack} to enchant
*
* @return true if the item has been enchanted
*/
private Map<Enchantment, Integer> handleMagicHunter(ItemStack treasureDrop) {
Map<Enchantment, Integer> enchants = new HashMap<Enchantment, Integer>();
List<EnchantmentTreasure> fishingEnchantments = null;
double diceRoll = Misc.getRandom().nextDouble() * 100;
for (Rarity rarity : Rarity.values()) {
if (rarity == Rarity.RECORD) {
continue;
}
double dropRate = TreasureConfig.getInstance().getEnchantmentDropRate(getLootTier(), rarity);
if (diceRoll <= dropRate) {
// Make sure enchanted books always get some kind of enchantment. --hoorigan
if (treasureDrop.getType() == Material.ENCHANTED_BOOK) {
diceRoll = dropRate + 1;
continue;
}
fishingEnchantments = TreasureConfig.getInstance().fishingEnchantments.get(rarity);
break;
}
diceRoll -= dropRate;
}
if (fishingEnchantments == null) {
return enchants;
}
List<Enchantment> validEnchantments = getPossibleEnchantments(treasureDrop);
List<EnchantmentTreasure> possibleEnchants = new ArrayList<EnchantmentTreasure>();
for (EnchantmentTreasure enchantmentTreasure : fishingEnchantments) {
if (validEnchantments.contains(enchantmentTreasure.getEnchantment())) {
possibleEnchants.add(enchantmentTreasure);
}
}
if (possibleEnchants.isEmpty()) {
return enchants;
}
// This make sure that the order isn't always the same, for example previously Unbreaking had a lot more chance to be used than any other enchant
Collections.shuffle(possibleEnchants, Misc.getRandom());
int specificChance = 1;
for (EnchantmentTreasure enchantmentTreasure : possibleEnchants) {
Enchantment possibleEnchantment = enchantmentTreasure.getEnchantment();
if (treasureDrop.getItemMeta().hasConflictingEnchant(possibleEnchantment) || Misc.getRandom().nextInt(specificChance) != 0) {
continue;
}
enchants.put(possibleEnchantment, enchantmentTreasure.getLevel());
specificChance *= 2;
}
return enchants;
}
private List<Enchantment> getPossibleEnchantments(ItemStack treasureDrop) {
Material dropType = treasureDrop.getType();
if (Fishing.ENCHANTABLE_CACHE.containsKey(dropType)) {
return Fishing.ENCHANTABLE_CACHE.get(dropType);
}
List<Enchantment> possibleEnchantments = new ArrayList<Enchantment>();
for (Enchantment enchantment : Enchantment.values()) {
if (enchantment.canEnchantItem(treasureDrop)) {
possibleEnchantments.add(enchantment);
}
}
Fishing.ENCHANTABLE_CACHE.put(dropType, possibleEnchantments);
return possibleEnchantments;
}
/**
* Gets the vanilla XP multiplier
*
* @return the vanilla XP multiplier
*/
private int getVanillaXpMultiplier() {
return getVanillaXPBoostModifier();
}
}

View File

@ -0,0 +1,142 @@
package com.gmail.nossr50.core.skills.primary.herbalism;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import java.util.HashSet;
public class Herbalism {
/**
* Convert blocks affected by the Green Thumb & Green Terra abilities.
*
* @param blockState
* The {@link BlockState} to check ability activation for
* @return true if the ability was successful, false otherwise
*/
protected static boolean convertGreenTerraBlocks(BlockState blockState) {
switch (blockState.getType()) {
case Material.COBBLESTONE_WALL:
blockState.setType(Material.MOSSY_COBBLESTONE_WALL);
return true;
case Material.STONE_BRICKS:
blockState.setType(Material.MOSSY_STONE_BRICKS);
return true;
case Material.DIRT :
case Material.GRASS_PATH :
blockState.setType(Material.GRASS_BLOCK);
return true;
case Material.COBBLESTONE :
blockState.setType(Material.MOSSY_COBBLESTONE);
return true;
default :
return false;
}
}
private static int calculateChorusPlantDrops(Block target) {
return calculateChorusPlantDropsRecursive(target, new HashSet<>());
}
private static int calculateChorusPlantDropsRecursive(Block target, HashSet<Block> traversed) {
if (target.getType() != Material.CHORUS_PLANT)
return 0;
// Prevent any infinite loops, who needs more than 64 chorus anyways
if (traversed.size() > 64)
return 0;
if (!traversed.add(target))
return 0;
int dropAmount = 0;
if (mcMMO.getPlaceStore().isTrue(target))
mcMMO.getPlaceStore().setFalse(target);
else
dropAmount++;
for (BlockFace blockFace : new BlockFace[] { BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST ,BlockFace.WEST})
dropAmount += calculateChorusPlantDropsRecursive(target.getRelative(blockFace, 1), traversed);
return dropAmount;
}
/**
* Calculate the drop amounts for multi block plants based on the blocks
* relative to them.
*
* @param blockState
* The {@link BlockState} of the bottom block of the plant
* @return the number of bonus drops to award from the blocks in this plant
*/
protected static int calculateMultiBlockPlantDrops(BlockState blockState) {
Block block = blockState.getBlock();
Material blockType = blockState.getType();
int dropAmount = mcMMO.getPlaceStore().isTrue(block) ? 0 : 1;
if (blockType == Material.CHORUS_PLANT) {
dropAmount = 1;
if (block.getRelative(BlockFace.DOWN, 1).getType() == Material.END_STONE) {
dropAmount = calculateChorusPlantDrops(block);
}
} else {
// Handle the two blocks above it - cacti & sugar cane can only grow 3 high naturally
for (int y = 1; y < 3; y++) {
Block relativeBlock = block.getRelative(BlockFace.UP, y);
if (relativeBlock.getType() != blockType) {
break;
}
if (mcMMO.getPlaceStore().isTrue(relativeBlock)) {
mcMMO.getPlaceStore().setFalse(relativeBlock);
} else {
dropAmount++;
}
}
}
return dropAmount;
}
/**
* Convert blocks affected by the Green Thumb & Green Terra abilities.
*
* @param blockState
* The {@link BlockState} to check ability activation for
* @return true if the ability was successful, false otherwise
*/
protected static boolean convertShroomThumb(BlockState blockState) {
switch (blockState.getType()) {
case Material.DIRT :
case Material.GRASS_BLOCK:
case Material.GRASS_PATH :
blockState.setType(Material.MYCELIUM);
return true;
default :
return false;
}
}
/**
* Check if the block has a recently grown crop from Green Thumb
*
* @param blockState
* The {@link BlockState} to check green thumb regrown for
* @return true if the block is recently regrown, false otherwise
*/
public static boolean isRecentlyRegrown(BlockState blockState) {
return blockState.hasMetadata(mcMMO.greenThumbDataKey) && !SkillUtils.cooldownExpired(blockState.getMetadata(mcMMO.greenThumbDataKey).get(0).asInt(), 1);
}
}

Some files were not shown because too many files have changed in this diff Show More