Merge api branch (NOT tested)

This commit is contained in:
Indyuce 2022-07-29 18:42:12 +02:00
commit adc4f03601
37 changed files with 1117 additions and 390 deletions

12
pom.xml
View File

@ -125,6 +125,11 @@
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/repository/public/</url>
</repository>
</repositories>
<dependencies>
@ -188,6 +193,13 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.citizensnpcs</groupId>
<artifactId>Citizens</artifactId>

View File

@ -28,7 +28,6 @@ import net.Indyuce.mmocore.guild.GuildModuleType;
import net.Indyuce.mmocore.guild.provided.Guild;
import net.Indyuce.mmocore.guild.provided.MMOCoreGuildModule;
import net.Indyuce.mmocore.listener.*;
import net.Indyuce.mmocore.listener.bungee.GetMMOCorePlayerListener;
import net.Indyuce.mmocore.listener.event.PlayerPressKeyListener;
import net.Indyuce.mmocore.listener.option.*;
import net.Indyuce.mmocore.listener.profession.FishingListener;
@ -110,6 +109,8 @@ public class MMOCore extends JavaPlugin {
public boolean shouldDebugSQL, hasBungee;
private static final int MYTHICLIB_COMPATIBILITY_INDEX = 7;
public MMOCore() {
plugin = this;
}
@ -185,12 +186,9 @@ public class MMOCore extends JavaPlugin {
// Checks if the server runs with Bungee
hasBungee = SpigotConfig.bungee & !Bukkit.getServer().getOnlineMode();
//Setups the channel for Bungee
if(hasBungee) {
getServer().getMessenger().registerOutgoingPluginChannel(this,"namespace:give_mmocore_player");
getServer().getMessenger().registerOutgoingPluginChannel(this,"namespace:get_mmocore_player");
getServer().getMessenger().registerIncomingPluginChannel(this,"namespace:get_mmocore_player",new GetMMOCorePlayerListener());
}
/*
* Resource regeneration. Must check if entity is dead otherwise regen will make
@ -277,9 +275,8 @@ public class MMOCore extends JavaPlugin {
getLogger().log(Level.WARNING, "Could not load hotbar swapping: " + exception.getMessage());
}
if (getConfig().getBoolean("prevent-spawner-xp")) {
if (getConfig().getBoolean("prevent-spawner-xp"))
Bukkit.getPluginManager().registerEvents(new NoSpawnerEXP(), this);
}
if (getConfig().getBoolean("death-exp-loss.enabled"))
Bukkit.getPluginManager().registerEvents(new DeathExperienceLoss(), this);
@ -300,12 +297,12 @@ public class MMOCore extends JavaPlugin {
/*
* Initialize player data from all online players. This is very important to do
* that after registering all the classes otherwise the player datas can't
* that after registering all the professses otherwise the player datas can't
* recognize what profess the player has and professes will be lost
*/
Bukkit.getOnlinePlayers().forEach(player -> dataProvider.getDataManager().setup(player.getUniqueId()));
// Load guild data after loading player data
// load guild data after loading player data
dataProvider.getGuildManager().load();
// Command

View File

@ -154,6 +154,9 @@ public class DefaultMMOLoader extends MMOLoader {
if (config.getKey().equals("craftitem"))
return new CraftItemExperienceSource(dispenser, config);
if (config.getKey().equals("fishitem"))
return new FishItemExperienceSource(dispenser, config);
return null;
}

View File

@ -27,6 +27,7 @@ import net.Indyuce.mmocore.experience.ExperienceTableClaimer;
import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.experience.droptable.ExperienceItem;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.guild.provided.Guild;
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
import net.Indyuce.mmocore.party.AbstractParty;
@ -84,6 +85,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
private final Map<String, SavedClassInformation> classSlots = new HashMap<>();
private final Map<PlayerActivity, Long> lastActivity = new HashMap<>();
/**
* Saves all the items that have been unlocked so far by
* the player. This is used for:
@ -244,6 +246,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
return skillPoints;
}
@Override
public int getClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item) {
String key = object.getKey() + "." + table.getId() + "." + item.getId();

View File

@ -85,6 +85,11 @@ public class MMOCoreUtils {
return t;
}
public static String toEnumName(String str) {
return str.replace("-","_").replace(" ","_").toUpperCase();
}
public static String toBase64(ItemStack[] items) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

View File

@ -2,19 +2,19 @@ package net.Indyuce.mmocore.gui;
import io.lumine.mythic.lib.manager.StatManager;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.event.PlayerAttributeUseEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.InventoryClickEvent;
public class AttributeView extends EditableInventory {
public AttributeView() {
@ -90,7 +90,7 @@ public class AttributeView extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equalsIgnoreCase("reallocation")) {
int spent = playerData.getAttributes().countSkillPoints();
@ -131,7 +131,7 @@ public class AttributeView extends EditableInventory {
}
// Amount of points spent
final boolean shiftClick = event.isShiftClick();
final boolean shiftClick = context.getClickType().isShiftClick();
int pointsSpent = shiftClick ? ((AttributeItem) item).shiftCost : 1;
if (attribute.hasMax())
pointsSpent = Math.min(pointsSpent, attribute.getMax() - ins.getBase());

View File

@ -5,6 +5,7 @@ import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
@ -107,10 +108,7 @@ public class ClassConfirmation extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
if (event.getInventory() != event.getClickedInventory())
return;
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("back"))
last.open();

View File

@ -1,8 +1,6 @@
package net.Indyuce.mmocore.gui;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.SoundEvent;
@ -11,15 +9,17 @@ import net.Indyuce.mmocore.api.player.profess.ClassOption;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.manager.InventoryManager;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.Comparator;
@ -82,10 +82,10 @@ public class ClassSelect extends EditableInventory {
lore.add(index + j, profess.getAttributeDescription().get(j));
}
meta.getPersistentDataContainer().set(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING, profess.getId());
meta.setLore(lore);
item.setItemMeta(meta);
return NBTItem.get(item).addTag(new ItemTag("classId", profess.getId())).toItem();
return item;
}
}
@ -103,10 +103,10 @@ public class ClassSelect extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("class")) {
String tag = NBTItem.get(event.getCurrentItem()).getString("classId");
if (tag.equals(""))
String classId = context.getItemStack().getItemMeta().getPersistentDataContainer().get(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING);
if (classId.equals(""))
return;
if (playerData.getClassPoints() < 1) {
@ -115,7 +115,7 @@ public class ClassSelect extends EditableInventory {
return;
}
PlayerClass profess = MMOCore.plugin.classManager.get(tag);
PlayerClass profess = MMOCore.plugin.classManager.get(classId);
if (profess.hasOption(ClassOption.NEEDS_PERMISSION) && !player.hasPermission("mmocore.class." + profess.getId().toLowerCase())) {
MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player);
new ConfigMessage("no-permission-for-class").send(player);
@ -141,7 +141,7 @@ public class ClassSelect extends EditableInventory {
* <p>
* It's also more RPG style to take the player back to the subclass
* he chose because that way he can't turn back and chose another path.
*
* <p>
* This does NOT function properly with subclass nets yet.
*
* @param root The root class, it's called the root because since the

View File

@ -13,6 +13,7 @@ import net.Indyuce.mmocore.experience.Booster;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
@ -22,7 +23,6 @@ import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
@ -183,7 +183,7 @@ public class PlayerStats extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext event, InventoryItem item) {
if (item.hasFunction())
if (item.getFunction().equals("boost-next")) {
boostOffset++;

View File

@ -6,6 +6,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.quest.Quest;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
@ -15,12 +16,16 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.checkerframework.checker.units.qual.N;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -162,9 +167,12 @@ public class QuestViewer extends EditableInventory {
meta.setDisplayName(holders.apply(inv.getPlayer(), getName()));
meta.addItemFlags(ItemFlag.values());
meta.setLore(lore);
meta.getPersistentDataContainer().set(new NamespacedKey(MMOCore.plugin,"quest_id"), PersistentDataType.STRING,quest.getId());
item.setItemMeta(meta);
return NBTItem.get(item).addTag(new ItemTag("questId", quest.getId())).toItem();
return item;
}
private Placeholders getPlaceholders(PlayerData data, Quest quest) {
@ -207,7 +215,7 @@ public class QuestViewer extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("previous")) {
page--;
open();
@ -221,11 +229,12 @@ public class QuestViewer extends EditableInventory {
}
if (item.getFunction().equals("quest")) {
String tag = NBTItem.get(event.getCurrentItem()).getString("questId");
if (tag.equals(""))
String questId = context.getItemStack().getItemMeta().getPersistentDataContainer()
.get(new NamespacedKey(MMOCore.plugin,"quest_id"), PersistentDataType.STRING);
if (questId.equals(""))
return;
Quest quest = MMOCore.plugin.questManager.get(tag);
Quest quest = MMOCore.plugin.questManager.get(questId);
if (playerData.getQuestData().hasCurrent()) {
@ -233,7 +242,7 @@ public class QuestViewer extends EditableInventory {
* check if the player is cancelling his ongoing quest.
*/
if (playerData.getQuestData().hasCurrent(quest)) {
if (event.getAction() == InventoryAction.PICKUP_HALF) {
if (context.getClickType() == ClickType.RIGHT) {
playerData.getQuestData().start(null);
MMOCore.plugin.soundManager.getSound(SoundEvent.CANCEL_QUEST).playTo(player);
MMOCore.plugin.configManager.getSimpleMessage("cancel-quest").send(player);

View File

@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.player.PlayerData;
@ -17,6 +18,7 @@ import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemFlag;
@ -283,7 +285,7 @@ public class SkillList extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
/*
if (skillSlots.contains(event.getRawSlot())
@ -296,7 +298,7 @@ public class SkillList extends EditableInventory {
*/
if (item.getFunction().equals("skill")) {
int index = skillSlots.size() * page + skillSlots.indexOf(event.getRawSlot());
int index = skillSlots.size() * page + skillSlots.indexOf(context.getSlot());
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
selected = skills.get(index);
open();
@ -321,11 +323,11 @@ public class SkillList extends EditableInventory {
* binding or unbinding skills.
*/
if (item.getFunction().equals("slot")) {
int index = slotSlots.indexOf(event.getRawSlot());
int index = slotSlots.indexOf(context.getSlot());
// unbind if there is a current spell.
if (event.getAction() == InventoryAction.PICKUP_HALF) {
if (context.getClickType() == ClickType.RIGHT) {
if (!playerData.hasSkillBound(index)) {
MMOCore.plugin.configManager.getSimpleMessage("no-skill-bound").send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
@ -384,7 +386,7 @@ public class SkillList extends EditableInventory {
return;
}
if (event.isShiftClick()) {
if (context.getClickType().isShiftClick()) {
if (playerData.getSkillPoints() < shiftCost) {
MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-points-shift", "shift_points", "" + shiftCost).send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);

View File

@ -5,6 +5,7 @@ import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
@ -50,9 +51,7 @@ public class SubclassConfirmation extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
if (event.getInventory() != event.getClickedInventory())
return;
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("back"))
last.open();

View File

@ -7,6 +7,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.manager.InventoryManager;
@ -107,12 +108,12 @@ public class SubclassSelect extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("back"))
InventoryManager.CLASS_SELECT.newInventory(playerData).open();
if (item.getFunction().equals("class")) {
String tag = NBTItem.get(event.getCurrentItem()).getString("classId");
String tag = NBTItem.get(context.getItemStack()).getString("classId");
if (tag.equals(""))
return;

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmocore.gui;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.player.PlayerActivity;
@ -222,7 +223,7 @@ public class WaypointViewer extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("next")) {
page++;
open();
@ -236,7 +237,7 @@ public class WaypointViewer extends EditableInventory {
}
if (item.getFunction().equals("waypoint")) {
PersistentDataContainer container = event.getCurrentItem().getItemMeta().getPersistentDataContainer();
PersistentDataContainer container = context.getItemStack().getItemMeta().getPersistentDataContainer();
String tag = container.has(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) ?
container.get(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) : "";

View File

@ -2,6 +2,8 @@ package net.Indyuce.mmocore.gui.api;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.api.adaptor.AdaptorType;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.TriggerItem;
import org.apache.commons.lang.Validate;
@ -16,12 +18,15 @@ import java.util.logging.Level;
public abstract class EditableInventory {
private final String id;
private AdaptorType adaptorType;
private String name;
private int slots;
protected double radius, angleGap, verticalGap, curvature, verticalOffset, interactSensitivity;
/*
* this set is linked so it keeps the order/priority in which the items are
* loaded from the config.
* This set is linked so it keeps the order/priority in
* which the items are loaded from the config.
*/
private final Set<InventoryItem> items = new LinkedHashSet<>();
@ -34,13 +39,22 @@ public abstract class EditableInventory {
public void reload(FileConfiguration config) {
this.adaptorType = AdaptorType.valueOf(MMOCoreUtils.toEnumName(config.getString("adaptor-type", "classic-adaptor")));
Validate.notNull(adaptorType, config.getString("adaptor-type") + " does not correspond to an adaptor-type.");//TODO
this.radius = config.getDouble("radius", 2);
this.angleGap = config.getDouble("angle-gap", 10);
this.verticalGap = config.getDouble("vertical-gap", 1);
this.curvature = config.getDouble("curvature", 1);
this.verticalOffset = config.getDouble("vertical-offset", 0);
this.interactSensitivity = config.getDouble("interact-sensitivity", 0.97);
this.name = config.getString("name");
Validate.notNull(name, "Name must not be null");
this.slots = Math.min(Math.max(9, config.getInt("slots")), 54);
Validate.isTrue((slots % 9) == 0, "Slots must be a multiple of 9");
items.clear();
if (config.contains("items")) {
Validate.notNull(config.getConfigurationSection("items"), "Could not load item list");
@ -72,6 +86,34 @@ public abstract class EditableInventory {
return slots;
}
public AdaptorType getAdaptorType() {
return adaptorType;
}
public double getRadius() {
return radius;
}
public double getAngleGap() {
return angleGap;
}
public double getVerticalGap() {
return verticalGap;
}
public double getInteractSensitivity() {
return interactSensitivity;
}
public double getCurvature() {
return curvature;
}
public double getVerticalOffset() {
return verticalOffset;
}
public InventoryItem getByFunction(String function) {
for (InventoryItem item : items)
if (item.getFunction().equals(function))

View File

@ -1,12 +1,11 @@
package net.Indyuce.mmocore.gui.api;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.gui.api.adaptor.Adaptor;
import net.Indyuce.mmocore.gui.api.adaptor.ClassicAdaptor;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.TriggerItem;
import org.bukkit.Bukkit;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -17,13 +16,13 @@ import java.util.function.Consumer;
public abstract class GeneratedInventory extends PluginInventory {
private final EditableInventory editable;
private final List<InventoryItem> loaded = new ArrayList<>();
private Inventory open;
private final Adaptor adaptor;
public GeneratedInventory(PlayerData playerData, EditableInventory editable) {
super(playerData);
this.editable = editable;
this.adaptor = editable.getAdaptorType().supply(this);
}
public List<InventoryItem> getLoaded() {
@ -59,13 +58,8 @@ public abstract class GeneratedInventory extends PluginInventory {
@Override
public Inventory getInventory() {
Inventory inv = Bukkit.createInventory(this, editable.getSlots(), MythicLib.plugin.getPlaceholderParser().parse(getPlayer(), calculateName()));
for (InventoryItem item : editable.getItems())
if (item.canDisplay(this))
item.setDisplayed(inv, this);
return inv;
Validate.isTrue(adaptor instanceof ClassicAdaptor);
return ((ClassicAdaptor) adaptor).getInventory();
}
public void open() {
@ -76,7 +70,7 @@ public abstract class GeneratedInventory extends PluginInventory {
*/
loaded.clear();
getPlayer().openInventory(open = getInventory());
adaptor.open();
}
/**
@ -85,28 +79,24 @@ public abstract class GeneratedInventory extends PluginInventory {
*/
@Deprecated
public void dynamicallyUpdateItem(InventoryItem<?> item, int n, ItemStack placed, Consumer<ItemStack> update) {
Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> {
update.accept(placed);
open.setItem(item.getSlots().get(n), placed);
});
adaptor.dynamicallyUpdateItem(item, n, placed, update);
}
public void whenClicked(InventoryClickEvent event) {
event.setCancelled(true);
if (event.getClickedInventory() != null && event.getClickedInventory().equals(event.getInventory())) {
InventoryItem item = getBySlot(event.getSlot());
public void whenClicked(InventoryClickContext context) {
context.setCancelled(true);
InventoryItem item = getBySlot(context.getSlot());
if (item == null)
return;
if (item instanceof TriggerItem)
((TriggerItem) item).getTrigger().apply(getPlayerData());
else
whenClicked(event, item);
}
whenClicked(context, item);
}
public abstract String calculateName();
public abstract void whenClicked(InventoryClickEvent event, InventoryItem item);
public abstract void whenClicked(InventoryClickContext context, InventoryItem item);
}

View File

@ -0,0 +1,56 @@
package net.Indyuce.mmocore.gui.api;
import org.bukkit.event.Cancellable;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class InventoryClickContext {
private final int slot;
private final ItemStack itemStack;
private final ClickType clickType;
private final Cancellable event;
private Inventory inv;
public InventoryClickContext(int slot, ItemStack itemStack, ClickType clickType, Cancellable event) {
this.slot = slot;
this.itemStack = itemStack;
this.clickType = clickType;
this.event = event;
}
public void setCancelled(boolean val) {
event.setCancelled(val);
}
public boolean isCancelled() {
return event.isCancelled();
}
public int getSlot() {
return slot;
}
public ItemStack getItemStack() {
return itemStack;
}
public Cancellable getEvent() {
return event;
}
public Inventory getInventory() {
return inv;
}
public boolean isClassic() {
return inv != null;
}
public ClickType getClickType() {
return clickType;
}
}

View File

@ -1,12 +1,9 @@
package net.Indyuce.mmocore.gui.api;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.InventoryHolder;
public abstract class PluginInventory implements InventoryHolder {
protected final Player player;
@ -30,13 +27,14 @@ public abstract class PluginInventory implements InventoryHolder {
return player;
}
/**
* Opens classic inventory, throws
*/
public void open() {
getPlayer().openInventory(getInventory());
}
public abstract Inventory getInventory();
public abstract void whenClicked(InventoryClickEvent event);
public abstract void whenClicked(InventoryClickContext context);
public void whenClosed(InventoryCloseEvent event) {
}

View File

@ -0,0 +1,22 @@
package net.Indyuce.mmocore.gui.api.adaptor;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import org.bukkit.inventory.ItemStack;
import java.util.function.Consumer;
public abstract class Adaptor {
protected final GeneratedInventory generated;
public Adaptor(GeneratedInventory generated) {
this.generated = generated;
}
public abstract void open();
public abstract void close();
@Deprecated
public abstract void dynamicallyUpdateItem(InventoryItem<?> item, int n, ItemStack placed, Consumer<ItemStack> update);
}

View File

@ -0,0 +1,20 @@
package net.Indyuce.mmocore.gui.api.adaptor;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import java.util.function.Function;
public enum AdaptorType {
CLASSIC_ADAPTOR(ClassicAdaptor::new),
THREE_DIM_ADAPTOR(ThreeDimAdaptor::new);
private final Function<GeneratedInventory, Adaptor> supplier;
AdaptorType(Function<GeneratedInventory, Adaptor> supplier) {
this.supplier = supplier;
}
public Adaptor supply(GeneratedInventory inv) {
return this.supplier.apply(inv);
}
}

View File

@ -0,0 +1,62 @@
package net.Indyuce.mmocore.gui.api.adaptor;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.function.Consumer;
public class ClassicAdaptor extends Adaptor {
private Inventory open;
public ClassicAdaptor(GeneratedInventory generated) {
super(generated);
}
@Override
public void open() {
generated.getPlayer().openInventory(open = getInventory());
}
@Override
public void close() {
}
@Override
public void dynamicallyUpdateItem(InventoryItem<?> item, int n, ItemStack placed, Consumer<ItemStack> update) {
Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> {
update.accept(placed);
open.setItem(item.getSlots().get(n), placed);
});
}
public Inventory getInventory() {
Inventory inv = Bukkit.createInventory(generated, generated.getEditable().getSlots(), MythicLib.plugin.getPlaceholderParser().parse(generated.getPlayer(), generated.calculateName()));
for (InventoryItem item : generated.getEditable().getItems())
if (item.canDisplay(generated))
setDisplayed(inv, item);
return inv;
}
private void setDisplayed(Inventory inv, InventoryItem item) {
generated.addLoaded(item);
List<Integer> slots = item.getSlots();
if (!item.hasDifferentDisplay()) {
ItemStack display = item.display(generated);
for (int slot : slots)
inv.setItem(slot, display);
} else
for (int j = 0; j < slots.size(); j++)
inv.setItem(slots.get(j), item.display(generated, j));
}
}

View File

@ -0,0 +1,499 @@
package net.Indyuce.mmocore.gui.api.adaptor;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import io.lumine.mythic.lib.api.util.TemporaryListener;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.function.Consumer;
public class ThreeDimAdaptor extends Adaptor {
private final double INITIAL_PERCENTAGE = 0.20;
private final double INCREMENT_PERCENTAGE = 0.20;
private SpawnPacketListener packetListener;
private InteractListener interactListener;
private final HashMap<Integer, ArmorStand> armorStands = new HashMap<>();
private final HashSet<ArmorStand> loreArmorStand = new HashSet<>();
private final HashMap<ItemStack, ArmorStand> hiddenArmorStand = new HashMap<>();
private boolean firstTime = true;
private final Vector direction = generated.getPlayer().getEyeLocation().getDirection().setY(0);
private final Location location = generated.getPlayer().getLocation().add(new Vector(0, generated.getEditable().getVerticalOffset(), 0));
//Zoomed=-1 no armorstand are under zoom
private int zoomed = -1;
public ThreeDimAdaptor(GeneratedInventory generated) {
super(generated);
}
@Override
public void open() {
if (!firstTime) {
fastClose();
fastOpen();
return;
}
firstTime = false;
//MMOCore.plugin.protocolManager.addPacketListener(packetListener = new SpawnPacketListener());
interactListener = new InteractListener();
for (InventoryItem item : generated.getEditable().getItems()) {
if (item.canDisplay(generated)) {
setInventoryItem(item, INITIAL_PERCENTAGE);
}
}
new BukkitRunnable() {
double total_percentage = INITIAL_PERCENTAGE;
@Override
public void run() {
if (total_percentage < 1) {
total_percentage += INCREMENT_PERCENTAGE;
for (int slot : armorStands.keySet()) {
armorStands.get(slot).teleport(getLocation(slot, total_percentage));
}
} else {
cancel();
}
}
}.runTaskTimer(MMOCore.plugin, 0L, 1L);
}
@Override
public void close() {
//Closes the packet listener,the interact listener and destroys the armor stands.
//MMOCore.plugin.protocolManager.removePacketListener(packetListener);
interactListener.close();
removeLore();
new BukkitRunnable() {
double total_percentage = 1;
@Override
public void run() {
if (total_percentage > INITIAL_PERCENTAGE) {
total_percentage -= INCREMENT_PERCENTAGE;
for (int slot : armorStands.keySet()) {
armorStands.get(slot).teleport(getLocation(slot, total_percentage));
}
} else {
for (ArmorStand armorStand : armorStands.values())
armorStand.remove();
cancel();
}
}
}.runTaskTimer(MMOCore.plugin, 0L, 1L);
}
/**
* Opens the inventory without the little animation
*/
public void fastOpen() {
//MMOCore.plugin.protocolManager.addPacketListener(packetListener = new SpawnPacketListener());
interactListener = new InteractListener();
for (InventoryItem item : generated.getEditable().getItems()) {
if (item.canDisplay(generated)) {
setInventoryItem(item, 1);
}
}
if (zoomed != -1) {
displayLore(zoomed);
armorStands.get(zoomed).teleport(getLocation(zoomed, 0.75));
}
}
/**
* Closes the inventory without the little animation
*/
public void fastClose() {
//Closes the packet listener,the interact listener and destroys the armor stands.
//MMOCore.plugin.protocolManager.removePacketListener(packetListener);
interactListener.close();
for (ArmorStand armorStand : armorStands.values())
armorStand.remove();
removeLore();
}
private void setInventoryItem(InventoryItem item, double percentage) {
generated.addLoaded(item);
List<Integer> slots = item.getSlots();
if (item.hasDifferentDisplay()) {
for (int i : slots) {
setItem(item.display(generated, i), i, percentage);
}
} else {
ItemStack itemStack = item.display(generated);
for (int i : slots) {
setItem(itemStack, i, percentage);
}
}
}
private void setItem(ItemStack item, int n, double percentage) {
Location location = getLocation(n, percentage);
//We create the armorStand corresponding to display the item
ArmorStand armorStand = (ArmorStand) generated.getPlayer().getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
armorStand.setVisible(false);
armorStand.setSmall(false);
armorStand.setArms(true);
armorStand.setGravity(false);
armorStand.getEquipment().setItem(EquipmentSlot.HEAD, item);
if (item.hasItemMeta() && item.getItemMeta().getDisplayName() != null) {
armorStand.setCustomName(item.getItemMeta().getDisplayName());
}
armorStand.setCustomNameVisible(true);
//We add properties to the PersistentDataContainer of the armor stand
PersistentDataContainer container = armorStand.getPersistentDataContainer();
container.set(new NamespacedKey(MMOCore.plugin, "slot"), PersistentDataType.INTEGER, n);
//Makes the ArmorStand look at you
//armorStand.setBodyPose(new EulerAngle(-direction.getX(),0,-direction.getZ()));
armorStands.put(n, armorStand);
}
public void displayLore(int n) {
ArmorStand armorStand = armorStands.get(n);
ItemStack itemStack = armorStand.getEquipment().getItem(EquipmentSlot.HEAD);
Location initalLocation = getLocation(n, 1);
for (ArmorStand armorStand1 : armorStands.values()) {
armorStand1.setCustomNameVisible(false);
}
Vector xAxis = initalLocation.clone().toVector().subtract(generated.getPlayer().getLocation().toVector()).setY(0).normalize();
Vector yAxis = new Vector(0, 1, 0);
Vector zAxis = xAxis.clone().rotateAroundAxis(yAxis, -Math.PI / 2);
//Empiric height of a line: 0.25
//Empiric size of a char: 0.13
double lineHeight = 0.25;
double charSize = 0.09;
//We search the biggest line in the lore
int max = 0;
for (String line : itemStack.getItemMeta().getLore()) {
if (line.length() > max)
max = line.length();
}
initalLocation.add(zAxis.clone().multiply(max * charSize / 2 + 0.8)).add(yAxis.clone().multiply(2 + 0.125 * itemStack.getItemMeta().getLore().size()));
for (String line : itemStack.getItemMeta().getLore()) {
if (line.length() != 0) {
ArmorStand as = (ArmorStand) initalLocation.getWorld().spawnEntity(initalLocation, EntityType.ARMOR_STAND);
as.setSmall(false);
as.setMarker(true);
as.setVisible(false);
as.setCustomNameVisible(true);
as.setCustomName(line);
loreArmorStand.add(as);
}
initalLocation.add(yAxis.clone().multiply(-lineHeight));
}
double totalHeight = lineHeight * itemStack.getItemMeta().getLore().size();
double totalLength = max * charSize;
Location topCorner = getLocation(n, 1).add(yAxis.clone().multiply(armorStand.getHeight() * 0.25 + totalHeight / 2));
//We remove the items that can be in the field of vision
for (int slot : armorStands.keySet()) {
ArmorStand otherArmorStand = armorStands.get(slot);
if (!otherArmorStand.equals(armorStand)) {
//Calculates the direction between the player and otherArmorStand
Vector direction = otherArmorStand.getLocation().add(new Vector(0, 0.25 * otherArmorStand.getHeight(), 0)).subtract(generated.getPlayer().getLocation()).toVector().normalize();
//The vector between the plan and the player.
//The plane normal is the xAxis
double t = (xAxis.clone().dot(topCorner.clone().subtract(generated.getPlayer().getLocation()).toVector())) / xAxis.clone().dot(direction);
Vector relativeProjection = generated.getPlayer().getLocation().toVector().add(direction.multiply(t)).subtract(topCorner.toVector());
//The intersection between 'direction' and the plane
//Vector projection=generated.getPlayer().getLocation().toVector().add(direction.clone().multiply(1/vector.dot(direction)));
//Vector relativeProjection=projection.subtract(topCorner.toVector());
double z = zAxis.dot(relativeProjection);
double y = (n / 9 - slot / 9) * lineHeight + totalHeight / 2;
if (z > 0 && z < totalLength && y > 0 && y < totalHeight) {
hideArmorStand(otherArmorStand);
}
}
}
}
/**
* Hide the item corrseponding to a certain armor stand if it hides the lore
*/
public void hideArmorStand(ArmorStand armorStand) {
hiddenArmorStand.put(armorStand.getEquipment().getItem(EquipmentSlot.HEAD), armorStand);
armorStand.getEquipment().setItem(EquipmentSlot.HEAD, null);
}
/**
* Reestablishes all the item for armor stand
*/
public void reestablishHiddenArmorStand() {
for (ItemStack item : hiddenArmorStand.keySet()) {
hiddenArmorStand.get(item).getEquipment().setItem(EquipmentSlot.HEAD, item);
}
hiddenArmorStand.clear();
}
public void removeLore() {
for (ArmorStand armorStand : loreArmorStand) {
armorStand.remove();
}
loreArmorStand.clear();
for (ArmorStand armorStand1 : armorStands.values()) {
armorStand1.setCustomNameVisible(true);
}
reestablishHiddenArmorStand();
}
public Location getLocation(int n, double percentage) {
//Determines the location at which the ArmorStand will spawn
Location cloneLocation = location.clone();
Vector cloneDirection = direction.clone().rotateAroundAxis(new Vector(0, 1, 0),
-((n % 9) - 4) * generated.getEditable().getAngleGap() * Math.PI / 180);
//Curvature of 1: r=cst Curvature of 1: r=R/cos(angle) (a plane)
double radius = percentage * generated.getEditable().getRadius() / Math.cos((1 - generated.getEditable().getCurvature())
* -((n % 9) - 4) * generated.getEditable().getAngleGap() * Math.PI / 180);
cloneDirection = cloneDirection.normalize().multiply(radius);
cloneDirection.add(new Vector(0, percentage * generated.getEditable().getVerticalGap() * ((generated.getEditable().getSlots() - n - 1) / 9), 1));
//We get the final direction
cloneLocation.add(cloneDirection);
cloneLocation.setDirection(new Vector(-cloneDirection.getX(), 0, -cloneDirection.getZ()));
return cloneLocation;
}
@Override
public void dynamicallyUpdateItem(InventoryItem<?> item, int n, ItemStack placed, Consumer<ItemStack> update) {
}
private class SpawnPacketListener extends PacketAdapter {
public SpawnPacketListener() {
super(MMOCore.plugin, PacketType.Play.Server.SPAWN_ENTITY_LIVING);
}
/**
* Cancels all the packet corresponding to an armorStand of the Gui to a player that should not see it.
*/
@Override
public void onPacketSending(PacketEvent event) {
PacketContainer packet = event.getPacket();
Entity entity = ProtocolLibrary.getProtocolManager()
.getEntityFromID(event.getPlayer().getWorld(), packet.getIntegers().read(0));
if (entity instanceof ArmorStand armorStand) {
if (true) {
Bukkit.broadcastMessage("IN");
if (armorStands.values().contains(armorStand)) {
Bukkit.broadcastMessage("CANCEL" + armorStand.getName());
event.setCancelled(true);
}
}
}
}
}
private class InteractListener extends TemporaryListener {
public InteractListener() {
super(MMOCore.plugin, PlayerInteractAtEntityEvent.getHandlerList()
, PlayerMoveEvent.getHandlerList(), PlayerInteractEvent.getHandlerList(), PlayerInteractAtEntityEvent.getHandlerList());
}
@EventHandler
public void onMove(PlayerMoveEvent e) {
if (e.getPlayer().equals(generated.getPlayer())) {
if (!e.getFrom().getBlock().getLocation().equals(e.getTo().getBlock().getLocation()))
ThreeDimAdaptor.this.close();
else {
//If the player no longer looks at the zoom as:
if (zoomed != -1 && generated.getPlayer().getLocation().getDirection().normalize().dot(
armorStands.get(zoomed).getLocation().add(new Vector(0, 0.25 * armorStands.get(zoomed).getHeight(), 0))
.subtract(generated.getPlayer().getLocation()).toVector().normalize()) < generated.getEditable().getInteractSensitivity()) {
armorStands.get(zoomed).teleport(getLocation(zoomed, 1));
zoomed = -1;
removeLore();
}
if (zoomed == -1) {
for (int n : armorStands.keySet()) {
ArmorStand as = armorStands.get(n);
Location asLocation = as.getLocation().add(new Vector(0, 0.25 * as.getHeight(), 0));
double scalar = generated.getPlayer().getLocation().getDirection().normalize().dot(
asLocation.subtract(generated.getPlayer().getLocation()).toVector().normalize());
if (scalar > generated.getEditable().getInteractSensitivity()) {
as.teleport(getLocation(n, 0.75));
zoomed = n;
displayLore(zoomed);
}
}
}
}
}
}
@EventHandler
public void onInteract(PlayerInteractAtEntityEvent event) {
if (event.getPlayer().equals(generated.getPlayer()))
if (event.getRightClicked() instanceof ArmorStand armorStand) {
if (armorStands.values().contains(armorStand)) {
PersistentDataContainer container = armorStand.getPersistentDataContainer();
int slot = container.get(new NamespacedKey(MMOCore.plugin, "slot"), PersistentDataType.INTEGER);
ClickType clickType;
if (event.getPlayer().isSneaking())
clickType = ClickType.SHIFT_RIGHT;
else
clickType = ClickType.RIGHT;
generated.whenClicked(new InventoryClickContext(slot, armorStand.getEquipment().getItem(EquipmentSlot.HEAD), clickType, event));
}
}
}
@EventHandler
public void onInteract(PlayerInteractEvent event) {
if (event.getPlayer().equals(generated.getPlayer())) {
Player player = event.getPlayer();
for (ArmorStand armorStand : armorStands.values()) {
//Little offset for the armorStand to have the location match the location of the itemstack
if (player.getLocation().getDirection().normalize()
.dot(armorStand.getLocation().add(new Vector(0, 0.25 * armorStand.getHeight(), 0)).subtract(player.getLocation()).toVector().normalize()) > 0.96) {
PersistentDataContainer container = armorStand.getPersistentDataContainer();
int slot = container.get(new NamespacedKey(MMOCore.plugin, "slot"), PersistentDataType.INTEGER);
ClickType clickType;
if (event.getAction() == Action.LEFT_CLICK_AIR) {
if (event.getPlayer().isSneaking())
clickType = ClickType.SHIFT_LEFT;
else
clickType = ClickType.LEFT;
} else if (event.getAction() == Action.RIGHT_CLICK_AIR) {
if (event.getPlayer().isSneaking())
clickType = ClickType.SHIFT_RIGHT;
else
clickType = ClickType.RIGHT;
} else {
return;
}
generated.whenClicked(new InventoryClickContext(slot, armorStand.getEquipment().getItem(EquipmentSlot.HEAD), clickType, event));
return;
}
}
}
}
@EventHandler
public void onDamage(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Player player) {
if (player.equals(generated.getPlayer()))
if (event.getEntity() instanceof ArmorStand armorStand) {
if (armorStands.values().contains(armorStand)) {
PersistentDataContainer container = armorStand.getPersistentDataContainer();
int slot = container.get(new NamespacedKey(MMOCore.plugin, "slot"), PersistentDataType.INTEGER);
ClickType clickType;
if (player.isSneaking())
clickType = ClickType.SHIFT_LEFT;
else
clickType = ClickType.LEFT;
ItemStack itemStack = armorStand.getEquipment().getItem(EquipmentSlot.HEAD);
generated.whenClicked(new InventoryClickContext(slot, itemStack, clickType, event));
}
}
}
}
@Override
public void whenClosed() {
}
}
}

View File

@ -4,6 +4,7 @@ import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.util.SmartGive;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import net.Indyuce.mmocore.util.item.SimpleItemBuilder;
import net.milkbowl.vault.economy.EconomyResponse;
@ -41,11 +42,11 @@ public class DepositMenu extends PluginInventory {
}
@Override
public void whenClicked(InventoryClickEvent event) {
if (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR)
public void whenClicked(InventoryClickContext event) {
if (event.getItemStack() == null || event.getItemStack().getType() == Material.AIR)
return;
if (event.getCurrentItem().isSimilar(depositItem)) {
if (event.getItemStack().isSimilar(depositItem)) {
event.setCancelled(true);
updateDeposit(event.getInventory());
@ -63,7 +64,7 @@ public class DepositMenu extends PluginInventory {
return;
}
int worth = NBTItem.get(event.getCurrentItem()).getInteger("RpgWorth");
int worth = NBTItem.get(event.getItemStack()).getInteger("RpgWorth");
if (worth < 1)
event.setCancelled(true);
else

View File

@ -1,26 +1,26 @@
package net.Indyuce.mmocore.gui.eco;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
public class GoldPouch extends PluginInventory {
private final boolean mob;
private final NBTItem nbt;
public GoldPouch(Player player, NBTItem nbt) {
super(player);
this.nbt = nbt;
this.mob = nbt.getBoolean("RpgPouchMob");
}
@ -33,27 +33,27 @@ public class GoldPouch extends PluginInventory {
}
@Override
public void whenClicked(InventoryClickEvent event) {
public void whenClicked(InventoryClickContext context) {
ItemStack item = event.getCurrentItem();
ItemStack item = context.getItemStack();
NBTItem nbt = NBTItem.get(item);
if (!nbt.hasTag("RpgWorth")) {
event.setCancelled(true);
context.setCancelled(true);
return;
}
if (mob) {
event.setCancelled(true);
context.setCancelled(true);
// in deposit menu
if (event.getRawSlot() < 18) {
if (context.getSlot() < 18) {
int empty = player.getInventory().firstEmpty();
if (empty < 0)
return;
player.playSound(player.getLocation(), Sound.ENTITY_SHULKER_TELEPORT, 1, 2);
player.getInventory().addItem(event.getCurrentItem());
event.setCurrentItem(null);
player.getInventory().addItem(context.getItemStack());
context.getInventory().setItem(context.getSlot(), null);
}
return;
@ -66,7 +66,7 @@ public class GoldPouch extends PluginInventory {
* contents
*/
if (nbt.hasTag("RpgPouchInventory"))
event.setCancelled(true);
context.setCancelled(true);
}
@Override

View File

@ -8,6 +8,7 @@ import net.Indyuce.mmocore.api.util.input.PlayerInput.InputType;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
@ -19,8 +20,7 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.Sound;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
@ -170,7 +170,7 @@ public class EditableFriendList extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("previous")) {
page--;
open();
@ -222,8 +222,8 @@ public class EditableFriendList extends EditableInventory {
});
}
if (item.getFunction().equals("friend") && event.getAction() == InventoryAction.PICKUP_HALF) {
String tag = event.getCurrentItem().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING);
if (item.getFunction().equals("friend") && context.getClickType() == ClickType.RIGHT) {
String tag = context.getItemStack().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING);
if (tag == null || tag.isEmpty())
return;

View File

@ -2,6 +2,7 @@ package net.Indyuce.mmocore.gui.social.friend;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.api.player.OfflinePlayerData;
import net.Indyuce.mmocore.api.player.PlayerData;
@ -47,7 +48,7 @@ public class EditableFriendRemoval extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("yes")) {
playerData.removeFriend(friend.getUniqueId());
OfflinePlayerData.get(friend.getUniqueId()).removeFriend(playerData.getUniqueId());

View File

@ -4,6 +4,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.input.ChatInput;
import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.player.PlayerData;
@ -17,6 +18,7 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.Sound;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
@ -135,7 +137,7 @@ public class EditableGuildAdmin extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("leave")) {
playerData.getGuild().removeMember(playerData.getUniqueId());
@ -184,11 +186,11 @@ public class EditableGuildAdmin extends EditableInventory {
});
}
if (item.getFunction().equals("member") && event.getAction() == InventoryAction.PICKUP_HALF) {
if (item.getFunction().equals("member") && context.getClickType() == ClickType.RIGHT) {
if (!playerData.getGuild().getOwner().equals(playerData.getUniqueId()))
return;
OfflinePlayer target = Bukkit.getOfflinePlayer(UUID.fromString(event.getCurrentItem().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING)));
OfflinePlayer target = Bukkit.getOfflinePlayer(UUID.fromString(context.getItemStack().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING)));
if (target.equals(player))
return;

View File

@ -4,6 +4,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.input.ChatInput;
import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.player.PlayerData;
@ -35,9 +36,7 @@ public class EditableGuildCreation extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
if (event.getInventory() != event.getClickedInventory())
return;
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("create")) {
new ChatInput(player, PlayerInput.InputType.GUILD_CREATION_TAG, (input) -> {

View File

@ -4,6 +4,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.input.ChatInput;
import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.player.OfflinePlayerData;
@ -15,6 +16,7 @@ import org.apache.commons.lang.Validate;
import org.bukkit.*;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
@ -161,7 +163,7 @@ public class EditableGuildView extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("leave")) {
playerData.getGuild().removeMember(playerData.getUniqueId());
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1);
@ -232,11 +234,11 @@ public class EditableGuildView extends EditableInventory {
});
}
if (item.getFunction().equals("member") && event.getAction() == InventoryAction.PICKUP_HALF) {
if (item.getFunction().equals("member") && context.getClickType() == ClickType.RIGHT) {
if (!playerData.getGuild().getOwner().equals(playerData.getUniqueId()))
return;
String tag = event.getCurrentItem().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING);
String tag = context.getItemStack().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING);
if (tag == null || tag.isEmpty())
return;

View File

@ -2,6 +2,7 @@ package net.Indyuce.mmocore.gui.social.party;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.player.PlayerData;
@ -32,9 +33,7 @@ public class EditablePartyCreation extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
if (event.getInventory() != event.getClickedInventory())
return;
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("create")) {
((MMOCorePartyModule) MMOCore.plugin.partyModule).newRegisteredParty(playerData);

View File

@ -1,20 +1,22 @@
package net.Indyuce.mmocore.gui.social.party;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.input.ChatInput;
import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.party.provided.Party;
import org.apache.commons.lang.Validate;
import org.bukkit.*;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
@ -131,7 +133,7 @@ public class EditablePartyView extends EditableInventory {
}
@Override
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
public void whenClicked(InventoryClickContext context, InventoryItem item) {
Party party = (Party) playerData.getParty();
if (item.getFunction().equals("leave")) {
@ -188,11 +190,11 @@ public class EditablePartyView extends EditableInventory {
});
}
if (item.getFunction().equals("member") && event.getAction() == InventoryAction.PICKUP_HALF) {
if (item.getFunction().equals("member") && context.getClickType() == ClickType.RIGHT) {
if (!party.getOwner().equals(playerData))
return;
OfflinePlayer target = Bukkit.getOfflinePlayer(UUID.fromString(event.getCurrentItem().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING)));
OfflinePlayer target = Bukkit.getOfflinePlayer(UUID.fromString(context.getItemStack().getItemMeta().getPersistentDataContainer().get(UUID_NAMESPACEDKEY, PersistentDataType.STRING)));
if (target.equals(player))
return;

View File

@ -7,6 +7,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -38,8 +39,15 @@ public class PlayerListener implements Listener {
// Register custom inventory clicks
@EventHandler
public void b(InventoryClickEvent event) {
if (event.getInventory().getHolder() instanceof PluginInventory)
((PluginInventory) event.getInventory().getHolder()).whenClicked(event);
if (event.getInventory().getHolder() instanceof PluginInventory) {
int slot = event.getRawSlot();
if (event.getCurrentItem() != null && event.getCurrentItem().getItemMeta() != null)
((PluginInventory) event.getInventory().getHolder())
.whenClicked(new InventoryClickContext(slot,event.getCurrentItem(),event.getClick(),event));
}
}
// Register custom inventory close effect

View File

@ -1,21 +0,0 @@
package net.Indyuce.mmocore.listener.bungee;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import java.util.UUID;
public class GetMMOCorePlayerListener implements PluginMessageListener {
@Override
public void onPluginMessageReceived( String channel, Player player, byte[] bytes) {
if(!channel.equals("give_mmocore_player"))
return;
ByteArrayDataInput input= ByteStreams.newDataInput(bytes);
UUID uuid=UUID.fromString(input.readUTF());
String Json=input.readUTF();
}
}

View File

@ -11,6 +11,7 @@ import net.Indyuce.mmocore.loot.chest.condition.Condition;
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.ArmorStand;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.loot.LootBuilder;
@ -30,7 +31,7 @@ public class DropTable extends PostLoadObject {
public DropTable(String id) {
super(null);
ArmorStand armorStand;
this.id = id;
}

View File

@ -6,6 +6,7 @@ import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.loot.LootBuilder;
import io.lumine.mythic.lib.api.MMOLineConfig;
import org.bukkit.Bukkit;
public abstract class DropItem {
protected static final Random random = new Random();
@ -14,6 +15,8 @@ public abstract class DropItem {
private final double chance, weight;
private final RandomAmount amount;
private static final double CHANCE_COEFFICIENT = 7. / 100;
public DropItem(MMOLineConfig config) {
chance = config.args().length > 0 ? Double.parseDouble(config.args()[0]) : 1;
amount = config.args().length > 1 ? new RandomAmount(config.args()[1]) : new RandomAmount(1, 1);
@ -36,6 +39,15 @@ public abstract class DropItem {
return amount.calculateInt();
}
/**
* CHANCE stat = 0 | tier chances are unchanged
* CHANCE stat = +inf | uniform law for any drop item
* CHANCE stat = 100 | all tier chances are taken their square root
*
* @return The real weight of an item considering the player's CHANCE stat.
*/
/**
* CHANCE stat = 0 | tier chances are unchanged
* CHANCE stat = +inf | uniform law for any drop item

View File

@ -133,6 +133,7 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
}
} catch (SQLException e) {
e.printStackTrace();
cancel();
}
});
}

View File

@ -5,7 +5,7 @@ author: Indyuce
description: ${project.description}
loadbefore: [MMOItems]
depend: [MythicLib]
softdepend: [Vault,MythicMobs,PlaceholderAPI,Residence,Citizens]
softdepend: [Vault,MythicMobs,PlaceholderAPI,Residence,Citizens,ProtocolLib]
api-version: 1.13
commands:
mmocore: