Mineplex2018-withcommit/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java

592 lines
19 KiB
Java
Raw Normal View History

package mineplex.game.clans.items;
import java.util.ArrayList;
2015-11-26 05:24:07 +01:00
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
2015-08-26 21:26:27 +02:00
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
2016-01-06 23:32:36 +01:00
import java.util.UUID;
2016-01-06 23:32:36 +01:00
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
2015-11-13 01:18:42 +01:00
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import mineplex.core.MiniPlugin;
import mineplex.core.account.CoreClientManager;
2016-01-06 23:32:36 +01:00
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.weight.Weight;
import mineplex.core.common.weight.WeightSet;
import mineplex.core.donation.DonationManager;
import mineplex.core.packethandler.IPacketHandler;
import mineplex.core.packethandler.PacketHandler;
import mineplex.core.packethandler.PacketInfo;
import mineplex.game.clans.items.attributes.AttributeContainer;
import mineplex.game.clans.items.attributes.AttributeType;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.attributes.armor.ConqueringArmorAttribute;
import mineplex.game.clans.items.attributes.armor.LavaAttribute;
import mineplex.game.clans.items.attributes.armor.PaddedAttribute;
import mineplex.game.clans.items.attributes.armor.ReinforcedAttribute;
import mineplex.game.clans.items.attributes.armor.SlantedAttribute;
import mineplex.game.clans.items.attributes.bow.HeavyArrowsAttribute;
import mineplex.game.clans.items.attributes.bow.HuntingAttribute;
import mineplex.game.clans.items.attributes.bow.InverseAttribute;
import mineplex.game.clans.items.attributes.bow.LeechingAttribute;
import mineplex.game.clans.items.attributes.bow.RecursiveAttribute;
import mineplex.game.clans.items.attributes.bow.ScorchingAttribute;
import mineplex.game.clans.items.attributes.bow.SlayingAttribute;
import mineplex.game.clans.items.attributes.weapon.ConqueringAttribute;
import mineplex.game.clans.items.attributes.weapon.FlamingAttribute;
import mineplex.game.clans.items.attributes.weapon.FrostedAttribute;
import mineplex.game.clans.items.attributes.weapon.HasteAttribute;
import mineplex.game.clans.items.attributes.weapon.JaggedAttribute;
import mineplex.game.clans.items.attributes.weapon.SharpAttribute;
import mineplex.game.clans.items.commands.GearCommand;
import mineplex.game.clans.items.economy.GoldToken;
import mineplex.game.clans.items.legendaries.AlligatorsTooth;
import mineplex.game.clans.items.legendaries.EnergyCrossbow;
import mineplex.game.clans.items.legendaries.GiantsBroadsword;
2015-11-25 02:32:05 +01:00
import mineplex.game.clans.items.legendaries.HyperAxe;
import mineplex.game.clans.items.legendaries.LegendaryItem;
2015-11-25 02:32:05 +01:00
import mineplex.game.clans.items.legendaries.MagneticMaul;
import mineplex.game.clans.items.legendaries.MeridianScepter;
import mineplex.game.clans.items.legendaries.WindBlade;
import mineplex.game.clans.items.rares.Crossbow;
import mineplex.game.clans.items.rares.RareItem;
import mineplex.game.clans.items.rares.RunedPickaxe;
import mineplex.game.clans.items.smelting.SmeltingListener;
import mineplex.game.clans.items.ui.GearShop;
import mineplex.serverdata.serialization.RuntimeTypeAdapterFactory;
2015-11-26 05:24:07 +01:00
import net.minecraft.server.v1_8_R3.NBTTagCompound;
2015-11-13 01:18:42 +01:00
import net.minecraft.server.v1_8_R3.Packet;
import net.minecraft.server.v1_8_R3.PacketPlayOutSetSlot;
import net.minecraft.server.v1_8_R3.PacketPlayOutWindowItems;
/**
2015-11-22 12:23:19 +01:00
* Manages creation and retrieval of associated {@link PlayerGear}s with online
* players, as well as offering methods for parsing and handling
* {@link CustomItem}s.
*
* @author MrTwiggy
2015-11-25 01:14:34 +01:00
*
*/
public class GearManager extends MiniPlugin implements IPacketHandler, Runnable
{
private static final String ITEM_SERIALIZATION_TAG = "-JSON-";
private static Gson _gson;
2015-11-22 12:23:19 +01:00
private static GearManager _instance; // Singleton instance
2015-11-22 12:23:19 +01:00
private Map<String, PlayerGear> _playerGears; // Mapping of player names
// (key) to cached gear set
// (value).
private WeightSet<Integer> _attributeWeights; // Weightings for randomly
// selecting number of
// attributes (1, 2, 3)
private WeightSet<ItemType> _typeWeights; // Weightings for randomly
// selecting item type
// (legendary/weapon/armor/bow)
private Set<String> _creativePlayers; // Set of names for all players
2015-11-25 01:14:34 +01:00
// currently in Creative gamemode
// Legendary generation
public WeightSet<Class<? extends LegendaryItem>> LegendaryWeights;
// Rare generation
public WeightSet<Class<? extends RareItem>> RareWeights;
// Weapon generation
public WeightSet<Material> WeaponTypes;
// Armor generation
public WeightSet<Material> ArmorTypes;
// Attribute generation
public WeightSet<Class<? extends ItemAttribute>> WeaponAttributes;
public WeightSet<Class<? extends ItemAttribute>> ArmorAttributes;
public WeightSet<Class<? extends ItemAttribute>> BowAttributes;
2015-11-26 05:24:07 +01:00
// Attribute Masks
private EnumSet<Material> _maskAttributes;
2015-11-22 12:23:19 +01:00
private GearShop _shop;
public GearManager(JavaPlugin plugin, PacketHandler packetHandler, CoreClientManager clientManager, DonationManager donationManager)
{
super("CustomGear", plugin);
_instance = this;
_shop = new GearShop(this, clientManager, donationManager);
_creativePlayers = new HashSet<String>();
_playerGears = new HashMap<String, PlayerGear>();
2015-11-22 12:23:19 +01:00
// TODO: Introduce configurable non-hardcoded values for generation
// weights?
_attributeWeights = new WeightSet<Integer>(new Weight<Integer>(3, 3), new Weight<Integer>(20, 2), new Weight<Integer>(77, 1));
2016-02-02 21:55:23 +01:00
_typeWeights = new WeightSet<ItemType>(new Weight<ItemType>(6, ItemType.LEGENDARY),
new Weight<ItemType>(46, ItemType.ARMOR),
new Weight<ItemType>(25, ItemType.WEAPON),
new Weight<ItemType>(23, ItemType.BOW));
// Weapon-based attributes
WeaponAttributes = new WeightSet<Class<? extends ItemAttribute>>(FrostedAttribute.class, SharpAttribute.class, JaggedAttribute.class, HasteAttribute.class, FlamingAttribute.class, ConqueringAttribute.class);
2015-11-22 12:23:19 +01:00
// Armor-based attributes
ArmorAttributes = new WeightSet<Class<? extends ItemAttribute>>(SlantedAttribute.class, ReinforcedAttribute.class, ConqueringArmorAttribute.class, PaddedAttribute.class, LavaAttribute.class);
// Bow-based attributes
BowAttributes = new WeightSet<Class<? extends ItemAttribute>>(HeavyArrowsAttribute.class, HuntingAttribute.class, InverseAttribute.class, LeechingAttribute.class, RecursiveAttribute.class, ScorchingAttribute.class, SlayingAttribute.class);
// Weapon material types
WeaponTypes = new WeightSet<Material>(Material.DIAMOND_SWORD, Material.GOLD_SWORD, Material.IRON_SWORD, Material.DIAMOND_AXE, Material.GOLD_AXE, Material.IRON_AXE);
// Armor material types
ArmorTypes = new WeightSet<Material>(Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS);
// TODO: Initialize list of attributes and types
// Initialize various LegendaryItem types
LegendaryWeights = new WeightSet<Class<? extends LegendaryItem>>(MeridianScepter.class, EnergyCrossbow.class, AlligatorsTooth.class, WindBlade.class, GiantsBroadsword.class, HyperAxe.class, MagneticMaul.class);
RareWeights = new WeightSet<Class<? extends RareItem>>(RunedPickaxe.class, Crossbow.class);
// TODO: Add rest of legendaries, find better way?
// Register listeners
UtilServer.getServer().getPluginManager().registerEvents(new ItemListener(getPlugin()), getPlugin());
UtilServer.getServer().getPluginManager().registerEvents(new SmeltingListener(), getPlugin());
// Initialize attribute types factory for JSON handling of polymorphism.
2015-11-22 12:23:19 +01:00
RuntimeTypeAdapterFactory<ItemAttribute> attributeFactory = RuntimeTypeAdapterFactory.of(ItemAttribute.class);
for (Class<? extends ItemAttribute> attributeType : ArmorAttributes.elements())
{
attributeFactory.registerSubtype(attributeType);
}
for (Class<? extends ItemAttribute> attributeType : WeaponAttributes.elements())
{
attributeFactory.registerSubtype(attributeType);
}
for (Class<? extends ItemAttribute> attributeType : BowAttributes.elements())
{
attributeFactory.registerSubtype(attributeType);
}
2015-11-22 12:23:19 +01:00
// Initialize legendary item type factory for JSON handling of
// polymorphism.
RuntimeTypeAdapterFactory<CustomItem> customItemType = RuntimeTypeAdapterFactory.of(CustomItem.class);
customItemType.registerSubtype(CustomItem.class);
customItemType.registerSubtype(LegendaryItem.class);
customItemType.registerSubtype(GoldToken.class);
for (Class<? extends CustomItem> itemType : LegendaryWeights.elements())
{
customItemType.registerSubtype(itemType);
}
// Build GSON instance off factories for future serialization of items.
2015-11-22 12:23:19 +01:00
_gson = new GsonBuilder().registerTypeAdapterFactory(attributeFactory).registerTypeAdapterFactory(customItemType).create();
2015-11-13 04:35:56 +01:00
packetHandler.addPacketHandler(this, PacketPlayOutSetSlot.class, PacketPlayOutWindowItems.class);
plugin.getServer().getScheduler().runTaskTimer(plugin, this, 1l, 1l);
2015-11-26 05:24:07 +01:00
_maskAttributes = EnumSet.of(Material.GOLD_RECORD, Material.GREEN_RECORD, Material.RECORD_3, Material.RECORD_4, Material.RECORD_5, Material.RECORD_6,
Material.RECORD_7, Material.RECORD_8, Material.RECORD_9, Material.RECORD_10, Material.RECORD_11, Material.RECORD_12);
}
@Override
public void addCommands()
{
addCommand(new GearCommand(this));
}
public void addCreativePlayer(Player player)
{
_creativePlayers.add(player.getName());
player.updateInventory();
}
public void removeCreativePlayer(Player player)
{
_creativePlayers.remove(player.getName());
player.updateInventory();
}
/**
2015-11-22 12:23:19 +01:00
* Tick & update internal logic for {@link GearManager}. Called once per
* tick.
*/
@Override
public void run()
{
2015-08-26 21:26:27 +02:00
Iterator<PlayerGear> iterator = _playerGears.values().iterator();
while (iterator.hasNext())
{
2015-08-26 21:26:27 +02:00
PlayerGear gear = iterator.next();
if (gear.isOnline())
{
gear.update();
}
else
{
2015-08-26 21:26:27 +02:00
iterator.remove();
}
}
}
@EventHandler
public void quit(PlayerQuitEvent event)
{
if (_playerGears.get(event.getPlayer().getName()) != null)
{
HandlerList.unregisterAll(_playerGears.get(event.getPlayer().getName()).getWeapon());
}
}
/**
* @param player - the player whose {@link PlayerGear} set is to be fetched.
2015-11-22 12:23:19 +01:00
* @return the cached or newly instantiated {@link PlayerGear} associated
* with {@code player}.
*/
public PlayerGear getPlayerGear(Player player)
{
String playerName = player.getName();
if (!_playerGears.containsKey(playerName))
{
PlayerGear gear = new PlayerGear(playerName);
_playerGears.put(playerName, gear);
}
return _playerGears.get(playerName);
}
public CustomItem generateItem()
{
int attributeCount = _attributeWeights.generateRandom();
ItemType itemType = _typeWeights.generateRandom();
RareItemFactory factory = RareItemFactory.begin(itemType);
if (itemType == ItemType.LEGENDARY)
{
factory.setLegendary(LegendaryWeights.generateRandom());
}
else if (itemType == ItemType.ARMOR)
{
factory.setType(ArmorTypes.generateRandom());
}
else if (itemType == ItemType.WEAPON)
{
factory.setType(WeaponTypes.generateRandom());
}
else if (itemType == ItemType.BOW)
{
factory.setType(Material.BOW);
}
2015-11-22 12:23:19 +01:00
if (itemType != ItemType.LEGENDARY) // Only non-legendaries have
// attributes
{
AttributeContainer attributes = new AttributeContainer();
generateAttributes(attributes, itemType, attributeCount);
2015-11-25 22:45:04 +01:00
System.out.println("Generating attributes...");
System.out.println("Remaining size: " + attributes.getRemainingTypes().size());
2015-11-22 12:23:19 +01:00
if (attributes.getSuperPrefix() != null)
{
2015-11-25 22:45:04 +01:00
System.out.println("Set super prefix: " + attributes.getSuperPrefix().getClass());
factory.setSuperPrefix(attributes.getSuperPrefix().getClass());
}
2015-11-22 12:23:19 +01:00
if (attributes.getPrefix() != null)
{
2015-11-25 22:45:04 +01:00
System.out.println("Set prefix: " + attributes.getPrefix().getClass());
factory.setPrefix(attributes.getPrefix().getClass());
2015-11-22 12:23:19 +01:00
}
if (attributes.getSuffix() != null)
{
2015-11-25 22:45:04 +01:00
System.out.println("Set suffix: " + attributes.getSuffix().getClass());
2015-11-22 12:23:19 +01:00
factory.setSuffix(attributes.getSuffix().getClass());
}
}
return factory.getWrapper();
}
private void generateAttributes(AttributeContainer container, ItemType type, int count)
{
for (int i = 0; i < count; i++)
{
int attempts = 0;
Set<AttributeType> remaining = container.getRemainingTypes();
ItemAttribute attribute = null;
while (remaining.size() > 0 && attempts < 10 && attribute == null)
{
ItemAttribute sampleAttribute = null;
switch (type)
{
2015-11-22 12:23:19 +01:00
case ARMOR:
sampleAttribute = instantiate(ArmorAttributes.generateRandom());
2015-11-22 12:23:19 +01:00
break;
case WEAPON:
sampleAttribute = instantiate(WeaponAttributes.generateRandom());
2015-11-22 12:23:19 +01:00
break;
case BOW:
sampleAttribute = instantiate(BowAttributes.generateRandom());
2015-11-22 12:23:19 +01:00
break;
default:
break;
}
if (sampleAttribute != null && remaining.contains(sampleAttribute.getType()))
{
2015-11-22 12:23:19 +01:00
attribute = sampleAttribute; // Select valid attribute to
// add
}
}
container.addAttribute(attribute);
}
}
public void spawnItem(Location location)
{
CustomItem item = generateItem();
location.getWorld().dropItem(location, item.toItemStack());
}
public static CustomItem parseItem(ItemStack item)
{
String serialization = getItemSerialization(item);
if (serialization != null)
{
2015-07-16 08:26:38 +02:00
CustomItem customItem = null;
2015-11-22 12:23:19 +01:00
try
2015-07-16 08:26:38 +02:00
{
customItem = deserialize(serialization);
}
catch (Exception exception)
{
2016-01-06 23:32:36 +01:00
exception.printStackTrace();
2015-07-16 08:26:38 +02:00
System.out.println("==========");
System.out.println("GearManager parse problem :");
System.out.println(serialization);
System.out.println("==========");
}
return customItem;
}
2015-11-22 12:23:19 +01:00
return null; // No serialization found in item's lore, not a custom
// item!
}
public static boolean isCustomItem(ItemStack item)
{
return getItemSerialization(item) != null;
}
public static String getItemSerialization(CustomItem customItem)
{
String serialization = serialize(customItem);
return ITEM_SERIALIZATION_TAG + serialization;
}
/**
2015-11-22 12:23:19 +01:00
* @param type - the class-type of the object to be instantiated. (must have
* zero-argument constructor)
* @return a newly instantiated instance of {@code type} class-type.
* Instantied with zero argument constructor.
*/
private static <T> T instantiate(Class<T> type)
{
2015-11-22 12:23:19 +01:00
try
{
return type.newInstance();
2015-11-22 12:23:19 +01:00
}
catch (Exception e)
{
return null;
2015-11-22 12:23:19 +01:00
}
}
private static String getItemSerialization(ItemStack item)
{
2015-11-22 12:23:19 +01:00
if (item == null || item.getItemMeta() == null || item.getItemMeta().getLore() == null) return null;
ItemMeta meta = item.getItemMeta();
for (String lore : meta.getLore())
{
2015-11-22 12:23:19 +01:00
if (lore.startsWith(ITEM_SERIALIZATION_TAG)) // Found serialization
// lore-line
{
int tagLength = ITEM_SERIALIZATION_TAG.length();
String serialization = lore.substring(tagLength);
return serialization;
}
}
2015-11-22 12:23:19 +01:00
return null; // Unable to find any serialized lore lines, hence not a
// CustomItem.
}
public static String serialize(CustomItem customItem)
{
return _gson.toJson(customItem, CustomItem.class);
}
public static String serialize(AttributeContainer attributes)
{
return _gson.toJson(attributes, AttributeContainer.class);
}
public static CustomItem deserialize(String serialization)
{
return _gson.fromJson(serialization, CustomItem.class);
}
public static <T> T deserialize(String serialization, Class<T> type)
{
return _gson.fromJson(serialization, type);
}
/**
* @return singleton instance of {@link GearManager}.
*/
public static GearManager getInstance()
{
return _instance;
}
public static void notify(Player player, String message)
{
UtilPlayer.message(player, F.main("Gear", message));
}
/**
2015-11-22 12:23:19 +01:00
* @param player - the player to see if they should have their out-going
* packets masked on CustomGear items.
* @return true, if the player should have their gear lore masked, false
* otherwise.
*/
private boolean maskGearPacket(Player player)
{
return player.getGameMode() != GameMode.CREATIVE && !_creativePlayers.contains(player.getName());
}
2015-11-22 12:23:19 +01:00
public void handle(PacketInfo packetInfo)
{
2015-11-22 12:23:19 +01:00
// Don't mask custom gear lore for creative players, as this will break
// them.
if (!maskGearPacket(packetInfo.getPlayer())) return;
2015-11-25 01:14:34 +01:00
Packet<?> packet = packetInfo.getPacket();
if (packet instanceof PacketPlayOutSetSlot)
2015-11-22 12:23:19 +01:00
{
PacketPlayOutSetSlot slotPacket = (PacketPlayOutSetSlot) packet;
2016-01-06 23:32:36 +01:00
slotPacket.c = maskItem(slotPacket.c, packetInfo.getPlayer()); // Mask all out-going item
2015-11-22 12:23:19 +01:00
// packets
}
else if (packet instanceof PacketPlayOutWindowItems)
{
PacketPlayOutWindowItems itemsPacket = (PacketPlayOutWindowItems) packet;
for (int i = 0; i < itemsPacket.b.length; i++)
{
2016-01-06 23:32:36 +01:00
itemsPacket.b[i] = maskItem(itemsPacket.b[i], packetInfo.getPlayer()); // Mask all
2015-11-22 12:23:19 +01:00
// out-going
// item packets
2015-11-26 05:24:07 +01:00
ItemStack item = CraftItemStack.asCraftMirror(itemsPacket.b[i]);
if (item != null && _maskAttributes.contains(item.getType()))
itemsPacket.b[i] = removeAttributes(itemsPacket.b[i]);
}
2015-11-22 12:23:19 +01:00
}
}
2015-11-26 05:24:07 +01:00
private net.minecraft.server.v1_8_R3.ItemStack removeAttributes(net.minecraft.server.v1_8_R3.ItemStack item)
{
if (item == null) return null;
if (item.getTag() == null)
{
item.setTag(new NBTTagCompound());
}
item.getTag().setInt("HideFlags", 62);
return item;
}
2016-01-06 23:32:36 +01:00
private net.minecraft.server.v1_8_R3.ItemStack maskItem(net.minecraft.server.v1_8_R3.ItemStack item, Player player)
{
2015-11-25 01:14:34 +01:00
// Cannot mask a null item
if (item == null)
{
return null;
}
CraftItemStack originalItem = CraftItemStack.asCraftMirror(item);
ItemMeta originalMeta = originalItem.getItemMeta();
2015-11-25 01:14:34 +01:00
// No need to modify item packets with no lore
if (originalMeta == null || originalMeta.getLore() == null)
{
return item;
}
List<String> lore = new ArrayList<String>();
2016-01-06 23:32:36 +01:00
CustomItem ci = parseItem(originalItem);
for (String line : originalMeta.getLore())
{
2016-01-06 23:32:36 +01:00
if (!line.startsWith(ITEM_SERIALIZATION_TAG))
{
lore.add(line);
}
}
if (ci != null && LegendaryWeights.elements().contains(ci.getClass()))
2016-01-06 23:32:36 +01:00
{
lore.add(C.cWhite + "Original Owner: " + C.cYellow + (ci.OriginalOwner == null ? "You" : Bukkit.getOfflinePlayer(UUID.fromString(ci.OriginalOwner)).getName()));
}
2015-11-13 01:18:42 +01:00
net.minecraft.server.v1_8_R3.ItemStack newItem = CraftItemStack.asNMSCopy(originalItem);
CraftItemStack newCopy = CraftItemStack.asCraftMirror(newItem);
ItemMeta newMeta = newCopy.getItemMeta();
newMeta.setLore(lore);
newCopy.setItemMeta(newMeta);
return newItem;
}
2015-11-22 12:23:19 +01:00
public void openShop(Player player)
{
_shop.attemptShopOpen(player);
}
}