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

401 lines
13 KiB
Java
Raw Normal View History

package mineplex.game.clans.items;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import mineplex.core.MiniPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.util.UtilServer;
import mineplex.core.packethandler.IPacketHandler;
import mineplex.core.packethandler.PacketHandler;
import mineplex.core.packethandler.PacketInfo;
import mineplex.core.portal.TransferHandler;
import mineplex.core.portal.Commands.SendCommand;
import mineplex.core.portal.Commands.ServerCommand;
import mineplex.game.clans.items.attributes.AttributeContainer;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.attributes.weapon.*;
import mineplex.game.clans.items.attributes.armor.*;
import mineplex.game.clans.items.attributes.bow.*;
import mineplex.game.clans.items.commands.GearCommand;
import mineplex.game.clans.items.economy.GoldToken;
import mineplex.game.clans.items.generation.Weight;
import mineplex.game.clans.items.generation.WeightSet;
import mineplex.game.clans.items.legendaries.*;
import mineplex.game.clans.items.smelting.SmeltingListener;
import mineplex.serverdata.Region;
import mineplex.serverdata.Utility;
import mineplex.serverdata.commands.ServerCommandManager;
import mineplex.serverdata.commands.TransferCommand;
import mineplex.serverdata.serialization.RuntimeTypeAdapterFactory;
import mineplex.serverdata.servers.ServerManager;
import net.minecraft.server.v1_7_R4.Packet;
import net.minecraft.server.v1_7_R4.PacketPlayOutSetSlot;
import net.minecraft.util.com.google.common.collect.Sets;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack;
import org.bukkit.entity.Player;
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;
/**
* 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
*
*/
public class GearManager extends MiniPlugin implements IPacketHandler, Runnable
{
private static final String ITEM_SERIALIZATION_TAG = "-JSON-";
private static Gson _gson;
private static GearManager _instance; // Singleton instance
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/armour/bow)
// Legendary generation
private WeightSet<Class<? extends LegendaryItem>> _legendaryWeights;
// Weapon generation
private WeightSet<Material> _weaponTypes;
// Armour generation
private WeightSet<Material> _armourTypes;
// Attribute generation
private WeightSet<Class<? extends ItemAttribute>> _weaponAttributes;
private WeightSet<Class<? extends ItemAttribute>> _armourAttributes;
private WeightSet<Class<? extends ItemAttribute>> _bowAttributes;
public GearManager(JavaPlugin plugin, PacketHandler packetHandler)
{
super("CustomGear", plugin);
_instance = this;
_playerGears = new HashMap<String, PlayerGear>();
// 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));
_typeWeights = new WeightSet<ItemType>(new Weight<ItemType>(10, ItemType.LEGENDARY),
new Weight<ItemType>(45, ItemType.ARMOUR),
new Weight<ItemType>(23, ItemType.WEAPON),
new Weight<ItemType>(22, ItemType.BOW));
// Weapon-based attributes
_weaponAttributes = new WeightSet<Class<? extends ItemAttribute>>(FrostedAttribute.class, SharpAttribute.class,
JaggedAttribute.class, HasteAttribute.class, FlamingAttribute.class, ConqueringAttribute.class);
// Armour-based attributes
_armourAttributes = new WeightSet<Class<? extends ItemAttribute>>(SlantedAttribute.class, ReinforcedAttribute.class,
ProtectionAttribute.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.STONE_SWORD,
Material.DIAMOND_AXE, Material.GOLD_AXE, Material.IRON_AXE, Material.STONE_AXE);
// Armour material types
_armourTypes = 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>>(AlligatorsTooth.class, WindBlade.class,
GiantsBroadsword.class, HyperBlade.class, MagneticBlade.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.
RuntimeTypeAdapterFactory<ItemAttribute> attributeFactory = RuntimeTypeAdapterFactory
.of(ItemAttribute.class);
for (Class<? extends ItemAttribute> attributeType : _armourAttributes.elements())
{
attributeFactory.registerSubtype(attributeType);
}
for (Class<? extends ItemAttribute> attributeType : _weaponAttributes.elements())
{
attributeFactory.registerSubtype(attributeType);
}
for (Class<? extends ItemAttribute> attributeType : _bowAttributes.elements())
{
attributeFactory.registerSubtype(attributeType);
}
// 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.
_gson = new GsonBuilder()
.registerTypeAdapterFactory(attributeFactory)
.registerTypeAdapterFactory(customItemType)
.create();
packetHandler.addPacketHandler(this);
plugin.getServer().getScheduler().runTaskTimer(plugin, this, 1l, 1l);
}
@Override
public void addCommands()
{
addCommand(new GearCommand(this));
}
/**
* Tick & update internal logic for {@link GearManager}. Called once per tick.
*/
@Override
public void run()
{
for (PlayerGear gear : _playerGears.values())
{
gear.update();
}
}
/**
* @param player - the player whose {@link PlayerGear} set is to be fetched.
* @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();
System.out.println("Generating item of type " + itemType.toString() + " with attribute count of " + attributeCount);
CustomItem item = generateItem(itemType);
System.out.println("Generated item!");
if (itemType != ItemType.LEGENDARY) // Only non-legendaries have attributes
{
for (ItemAttribute attribute : generateAttributes(itemType, attributeCount))
{
item.addAttribute(attribute);
}
// Add up to attributeCount attributes
}
return item;
}
private CustomItem generateItem(ItemType itemType)
{
switch(itemType)
{
case LEGENDARY: // Legendary weapon
Class<? extends LegendaryItem> legendaryClass = _legendaryWeights.generateRandom();
System.out.println("Legendary: " + legendaryClass.getName());
return instantiate(legendaryClass);
case WEAPON: // Sword or axe
return new CustomItem(_weaponTypes.generateRandom());
case ARMOUR: // Helmet, chestplate, leggings, or boots
return new CustomItem(_armourTypes.generateRandom());
case BOW: // A bow
return new CustomItem(Material.BOW);
default:
return null;// Never reached, yet required for compilation purposes.
}
}
private Set<ItemAttribute> generateAttributes(ItemType type, int count)
{
Set<ItemAttribute> attributes = new HashSet<ItemAttribute>();
for (int i = 0; i < count; i++)
{
switch (type)
{
case ARMOUR:
attributes.add(instantiate(_armourAttributes.generateRandom()));
break;
case WEAPON:
attributes.add(instantiate(_weaponAttributes.generateRandom()));
break;
case BOW:
attributes.add(instantiate(_bowAttributes.generateRandom()));
break;
default:
break;
}
}
return attributes;
}
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)
{
CustomItem customItem = deserialize(serialization);
return customItem;
}
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;
}
/**
* @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)
{
try
{
return type.newInstance();
}
catch (Exception e)
{
return null;
}
}
private static String getItemSerialization(ItemStack item)
{
if (item == null || item.getItemMeta() == null
|| item.getItemMeta().getLore() == null) return null;
ItemMeta meta = item.getItemMeta();
for (String lore : meta.getLore())
{
if (lore.startsWith(ITEM_SERIALIZATION_TAG)) // Found serialization lore-line
{
int tagLength = ITEM_SERIALIZATION_TAG.length();
String serialization = lore.substring(tagLength);
return serialization;
}
}
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 getInstane()
{
return _instance;
}
@Override
public void handle(PacketInfo packetInfo)
{
Packet packet = packetInfo.getPacket();
if (packet instanceof PacketPlayOutSetSlot)
{
System.out.println("Item slot packet!");
PacketPlayOutSetSlot slotPacket = (PacketPlayOutSetSlot) packet;
net.minecraft.server.v1_7_R4.ItemStack original = slotPacket.c;
CraftItemStack originalItem = CraftItemStack.asCraftMirror(original);
ItemMeta originalMeta = originalItem.getItemMeta();
if (originalMeta == null || originalMeta.getLore() == null) return; // No need to modify item packets with no lore
List<String> lore = new ArrayList<String>();
for (String line : originalMeta.getLore())
{
if (!line.startsWith(ITEM_SERIALIZATION_TAG)) // Remove serialization lines from out-going lore
{
lore.add(line);
}
}
net.minecraft.server.v1_7_R4.ItemStack newItem = CraftItemStack.asNMSCopy(originalItem);
CraftItemStack newCopy = CraftItemStack.asCraftMirror(newItem);
ItemMeta newMeta = newCopy.getItemMeta();
newMeta.setLore(lore);
newCopy.setItemMeta(newMeta);
slotPacket.c = newItem;
//CraftItemStack.setItemMeta(slotPacket.c, meta);
// TODO: Modify spigot build so that slotPacket's itemstack lore can be modified
// to 'hide' json-encoded lore from players.
}
}
}