Convert damage system to custom Mineplex damage events to enable legendary abilities. Fix NPE and hanging issue on ServerData's serialization adapter. Finalize item generation logic for instantiating CustomItem's based on specified random distribution of types, attribute counts, etc. Fix several Legendary bugs discovered during testing. Clean left-over template documentation and further clarify ambiguous methods. Add proper updating logic for custom items to track internal stats in hidden json lore. Add safe-logout system to prevent combat logging and enable players to safely log after a designated amount of time. Tweak WindBlade's flight speed to a more natural value.

This commit is contained in:
Ty Sayers 2015-06-01 12:25:20 -04:00
parent 167549c9e8
commit 2e19aabfa1
34 changed files with 819 additions and 177 deletions

View File

@ -0,0 +1,251 @@
package mineplex.game.clans.gameplay.safelog;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import mineplex.core.MiniPlugin;
import mineplex.minecraft.game.core.combat.event.CombatDeathEvent;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import mineplex.minecraft.game.core.damage.DamageManager;
import mineplex.core.itemstack.ItemStackFactory;
import mineplex.core.recharge.Recharge;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.core.updater.UpdateType;
import mineplex.core.blockrestore.BlockRestore;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilEvent;
import mineplex.core.common.util.UtilGear;
import mineplex.core.common.util.UtilInv;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilEvent.ActionType;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.items.commands.GearCommand;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Effect;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockIgniteEvent.IgniteCause;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.plugin.java.JavaPlugin;
public class LoggingManager extends MiniPlugin
{
public static final double SAFE_LOG_RANGE = 32d;
public static final int LOGOUT_DURATION = 10000; // Duration of safe-log (in milliseconds)
public static final long REJOIN_TIME = 60000;
//Track Offline Players
private HashMap<String, LogoutData> _logouts = new HashMap<String, LogoutData>();
public LoggingManager(JavaPlugin plugin)
{
super("Logout Manager", plugin);
_logouts = new HashMap<String, LogoutData>();
}
private Set<Player> getNearbyHostilePlayers(Location location, double radius)
{
Set<Player> nearbyPlayers = new HashSet<Player>();
for (Player player : location.getWorld().getPlayers())
{
double radiusSquared = radius * radius;
if (player.getLocation().distanceSquared(location) <= radiusSquared) // TODO: Check to see if they're in a clan?
{
nearbyPlayers.add(player);
}
}
return nearbyPlayers;
}
public void onPlayerQuit(Player player)
{
LogoutData logoutData = _logouts.remove(player);
boolean isSafeLog = logoutData != null && logoutData.hasSafeLogout() && !player.isDead();
if (!isSafeLog && getNearbyHostilePlayers(player.getLocation(), 32d).size() == 1) // No other players within 32 blocks
{
isSafeLog = true;
}
// TODO: Check to see if player was attacked or attacked another player within last 15 seconds and set isSafeLog=false...
if (!isSafeLog)
{
onCombatLog(player);
}
}
public void onPlayerJoin(Player player)
{
// TODO: Check to see if the player has a combat-log bot in place
// and if so, remove/un-use it as they have logged back in.
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event)
{
onPlayerQuit(event.getPlayer());
}
@EventHandler
public void onPlayerKicked(PlayerKickEvent event)
{
onPlayerQuit(event.getPlayer());
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event)
{
onPlayerJoin(event.getPlayer());
}
@EventHandler
public void onUpdate(UpdateEvent event)
{
if (event.getType() == UpdateType.TICK)
tick();
}
@Override
public void addCommands()
{
addCommand(new QuitCommand(this));
}
private LogoutData getLogoutData(Player player)
{
return _logouts.get(player.getName());
}
public LogoutData insertLogoutData(Player player, long duration)
{
LogoutData data = new LogoutData(player, duration);
_logouts.put(player.getName(), data);
return data;
}
public LogoutData insertLogoutData(Player player)
{
return insertLogoutData(player, LOGOUT_DURATION);
}
public boolean hasLogoutData(Player player)
{
return getLogoutData(player) != null;
}
/**
* Tick the internal logic of this manager and update it's state.
* Intended to be ticked/updated every in-game tick.
*/
private void tick()
{
for (String playerName : _logouts.keySet())
{
LogoutData data = _logouts.get(playerName);
if (data.isOnline())
{
double distance = data.getDistanceTravelled();
if (distance >= SAFE_LOG_RANGE)
{
cancelSafeLog(data.getPlayer());
}
else if (data.hasSafeLogout())
{
// TODO: Log out player safely.
}
}
else
{
_logouts.remove(playerName);
}
}
}
private void cancelSafeLog(Player player)
{
_logouts.remove(player.getName());
// TODO: Notify player that safe-log was cancelled
}
public void onCombatLog(Player player)
{
UtilInv.drop(player, true); // Drop player's inventory belongigs to ground
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event)
{
Player player = event.getPlayer();
if (hasLogoutData(player))
{
cancelSafeLog(player);
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onEntityDamaged(EntityDamageByEntityEvent event)
{
Entity victim = event.getEntity();
if (victim instanceof Player)
{
Player player = (Player) victim;
if (hasLogoutData(player))
{
cancelSafeLog(player);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onItemPickup(PlayerPickupItemEvent event)
{
if (hasLogoutData(event.getPlayer()))
{
event.setCancelled(true); // Prevent players that are safe-logging from picking up items.
}
}
}

View File

@ -0,0 +1,46 @@
package mineplex.game.clans.gameplay.safelog;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class LogoutData
{
private String _playerName;
public Player getPlayer() { return Bukkit.getPlayer(_playerName); }
private long _endTime;
public boolean hasSafeLogout() { return System.currentTimeMillis() >= _endTime; }
private long _startTime;
private Location _location;
public Location getLocation() { return _location; }
public LogoutData(Player player, long duration)
{
_startTime = System.currentTimeMillis();
_endTime = _startTime + duration;
_location = player.getLocation();
_playerName = player.getName();
}
public boolean isOnline()
{
Player player = getPlayer();
return player != null && player.isOnline();
}
public double getDistanceTravelled()
{
if (isOnline())
{
Player player = getPlayer();
return player.getLocation().distance(_location);
}
return -1d;
}
}

View File

@ -0,0 +1,62 @@
package mineplex.game.clans.gameplay.safelog;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilInput;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilTime.TimeUnit;
import mineplex.core.common.util.UtilWorld;
import mineplex.core.recharge.Recharge;
import mineplex.game.clans.clans.ClanInfo;
import mineplex.game.clans.clans.ClanRole;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.ClansUtility.ClanRelation;
import mineplex.game.clans.clans.ClientClan;
import mineplex.game.clans.items.CustomItem;
import mineplex.game.clans.items.GearManager;
import mineplex.game.clans.items.attributes.weapon.FlamingAttribute;
import mineplex.game.clans.items.attributes.weapon.FrostedAttribute;
import mineplex.game.clans.items.attributes.weapon.SharpAttribute;
import mineplex.game.clans.items.legendaries.LegendaryItem;
import mineplex.game.clans.items.legendaries.WindBlade;
public class QuitCommand extends CommandBase<LoggingManager>
{
private LoggingManager _loggingManager;
public QuitCommand(LoggingManager plugin)
{
super(plugin, Rank.ALL, "quit", "log", "logout");
_loggingManager = plugin;
}
@Override
public void Execute(Player caller, String[] args)
{
if (_loggingManager.hasLogoutData(caller))
{
UtilPlayer.message(caller, F.main("SafeLog", "You are already safe-logging!"));
}
else
{
_loggingManager.insertLogoutData(caller);
UtilPlayer.message(caller, F.main("SafeLog", "Successfully initiated safe-log!"));
}
}
}

View File

@ -7,6 +7,7 @@ import java.util.Set;
import java.util.UUID;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.Material;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@ -32,7 +33,7 @@ public class CustomItem
private ItemAttribute _suffix;
public void setSuffix(ItemAttribute attribute) { _suffix = attribute; }
private String _displayName;
protected String _displayName;
private String _description;
private Material _material;
@ -117,6 +118,11 @@ public class CustomItem
return item;
}
public ItemStack toItemStack()
{
return toItemStack(1);
}
public void onInteract(PlayerInteractEvent event)
{
System.out.println("Triggered interact!");
@ -126,7 +132,7 @@ public class CustomItem
}
}
public void onAttack(EntityDamageByEntityEvent event)
public void onAttack(CustomDamageEvent event)
{
System.out.println("Triggered attack!");
for (ItemAttribute attribute : getAttributes())
@ -135,7 +141,7 @@ public class CustomItem
}
}
public void onAttacked(EntityDamageByEntityEvent event)
public void onAttacked(CustomDamageEvent event)
{
System.out.println("Triggered damage!");
for (ItemAttribute attribute : getAttributes())
@ -182,4 +188,20 @@ public class CustomItem
item.setItemMeta(meta);
}
public void addAttribute(ItemAttribute attribute)
{
if (_superPrefix == null)
{
_superPrefix = attribute;
}
else if (_prefix == null)
{
_prefix = attribute;
}
else if (_suffix == null)
{
_suffix = attribute;
}
}
}

View File

@ -1,8 +1,12 @@
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;
@ -14,14 +18,12 @@ import mineplex.core.portal.TransferHandler;
import mineplex.core.portal.Commands.SendCommand;
import mineplex.core.portal.Commands.ServerCommand;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.attributes.weapon.FlamingAttribute;
import mineplex.game.clans.items.attributes.weapon.FrostedAttribute;
import mineplex.game.clans.items.attributes.weapon.SharpAttribute;
import mineplex.game.clans.items.attributes.weapon.*;
import mineplex.game.clans.items.attributes.armor.*;
import mineplex.game.clans.items.commands.GearCommand;
import mineplex.game.clans.items.generation.Weight;
import mineplex.game.clans.items.generation.WeightSet;
import mineplex.game.clans.items.legendaries.AlligatorsTooth;
import mineplex.game.clans.items.legendaries.WindBlade;
import mineplex.game.clans.items.legendaries.*;
import mineplex.game.clans.items.smelting.SmeltingListener;
import mineplex.serverdata.Region;
import mineplex.serverdata.Utility;
@ -31,8 +33,11 @@ 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.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -47,17 +52,31 @@ import com.google.gson.GsonBuilder;
* @author MrTwiggy
*
*/
public class GearManager extends MiniPlugin implements IPacketHandler
public class GearManager extends MiniPlugin implements IPacketHandler, Runnable
{
private static final String ITEM_SERIALIZATION_TAG = "-JSON-";
private static Random random = new Random();
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 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<Boolean> _itemWeights; // Weightings for randomly selecting item type (legendary/rare)
private WeightSet<Boolean> _gearWeights; // Weightings for randomly selecting gear type (armour/weapon)
private static Gson _gson;
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)
{
@ -65,37 +84,77 @@ public class GearManager extends MiniPlugin implements IPacketHandler
_instance = this;
playerGears = new HashMap<String, PlayerGear>();
_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));
_itemWeights = new WeightSet<Boolean>(new Weight<Boolean>(90, true), new Weight<Boolean>(10, false));
_itemWeights = new WeightSet<Boolean>(new Weight<Boolean>(50, true), new Weight<Boolean>(50, false));
_attributeWeights = new WeightSet<Integer>(new Weight<Integer>(3, 3), new Weight<Integer>(20, 2), new Weight<Integer>(77, 1), new Weight<Integer>(80, 0));
_typeWeights = new WeightSet<ItemType>(new Weight<ItemType>(1000, ItemType.LEGENDARY),
new Weight<ItemType>(45, ItemType.ARMOUR),
new Weight<ItemType>(22, ItemType.WEAPON),
new Weight<ItemType>(22, ItemType.BOW));
System.out.println("-Testting-testing");
System.out.println(Utility.currentTimeSeconds());
// 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>>(); // TODO: Add in bow-attributes
// 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());
UtilServer.getServer().getPluginManager().registerEvents(new SmeltingListener(), getPlugin());
// adding all different container classes with their flag
RuntimeTypeAdapterFactory<ItemAttribute> typeFactory = RuntimeTypeAdapterFactory
.of(ItemAttribute.class, "AttributeType")
.registerSubtype(SharpAttribute.class)
.registerSubtype(FrostedAttribute.class)
.registerSubtype(FlamingAttribute.class); // TODO: Register all item attributes automatically
// 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);
}
// Initialize legendary item type factory for JSON handling of polymorphism.
RuntimeTypeAdapterFactory<CustomItem> customItemType = RuntimeTypeAdapterFactory
.of(CustomItem.class, "ItemType")
.registerSubtype(AlligatorsTooth.class)
.registerSubtype(WindBlade.class); // TODO: Register all legendary weapons automatically
.of(CustomItem.class);
customItemType.registerSubtype(CustomItem.class);
customItemType.registerSubtype(LegendaryItem.class);
for (Class<? extends CustomItem> itemType : _legendaryWeights.elements())
{
customItemType.registerSubtype(itemType);
}
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapterFactory(typeFactory);
builder.registerTypeAdapterFactory(customItemType);
_gson = builder.create();
// 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
@ -104,6 +163,18 @@ public class GearManager extends MiniPlugin implements IPacketHandler
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}.
@ -111,24 +182,81 @@ public class GearManager extends MiniPlugin implements IPacketHandler
public PlayerGear getPlayerGear(Player player)
{
String playerName = player.getName();
if (!playerGears.containsKey(playerName))
if (!_playerGears.containsKey(playerName))
{
PlayerGear gear = new PlayerGear(playerName);
playerGears.put(playerName, gear);
_playerGears.put(playerName, gear);
}
return playerGears.get(playerName);
return _playerGears.get(playerName);
}
public CustomItem generateItem()
{
int attributeCount = _attributeWeights.generateRandom();
boolean isLegendary = _itemWeights.generateRandom();
boolean isArmour = _gearWeights.generateRandom();
ItemType itemType = _typeWeights.generateRandom();
// TODO: Generate custom item randomly using generated values above
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>();
return null;
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;
default:
break;
}
}
return attributes;
}
public void spawnItem(Location location)
{
CustomItem item = generateItem();
location.getWorld().dropItem(location, item.toItemStack());
}
public static CustomItem parseItem(ItemStack item)
@ -158,7 +286,7 @@ public class GearManager extends MiniPlugin implements IPacketHandler
{
if (i % 40 == 39)
{
serialization += "\n";
serialization += "\n"; // TODO: Remove this temporary fix to hiding player lore
}
serialization += tempSeri.charAt(i);
@ -167,6 +295,22 @@ public class GearManager extends MiniPlugin implements IPacketHandler
return 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
@ -214,12 +358,11 @@ public class GearManager extends MiniPlugin implements IPacketHandler
public static String serialize(CustomItem customItem)
{
return _gson.toJson(customItem);
return _gson.toJson(customItem, CustomItem.class);
}
public static CustomItem deserialize(String serialization)
{
System.out.println("Serialization: " + serialization);
return _gson.fromJson(serialization, CustomItem.class);
}
@ -241,7 +384,8 @@ public class GearManager extends MiniPlugin implements IPacketHandler
System.out.println("Item slot packet!");
PacketPlayOutSetSlot slotPacket = (PacketPlayOutSetSlot) packet;
// TODO: Modify spigot build so that slotPacket's itemstack lore can be modified
// to 'hide' json-encoded lore from players.
}
}
}

View File

@ -1,5 +1,7 @@
package mineplex.game.clans.items;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -50,21 +52,22 @@ public class ItemListener implements Listener
* @param event
*/
@EventHandler
public void onPlayerAttack(EntityDamageByEntityEvent event)
public void onPlayerAttack(CustomDamageEvent event)
{
Player damager = event.GetDamagerPlayer(true);
Player damagee = event.GetDamageePlayer();
// Trigger custom gear effects for attacker
if (event.getDamager() instanceof Player)
if (damager != null)
{
Player attacker = (Player) event.getDamager();
PlayerGear attackerGear = getGear(attacker);
PlayerGear attackerGear = getGear(damager);
attackerGear.onAttack(event);
}
// Trigger custom gear effects for defender
if (event.getEntity() instanceof Player)
if (damagee != null)
{
Player defender = (Player) event.getEntity();
PlayerGear defenderGear = getGear(defender);
PlayerGear defenderGear = getGear(damagee);
defenderGear.onAttacked(event);
}
}

View File

@ -0,0 +1,18 @@
package mineplex.game.clans.items;
import com.google.common.collect.Sets;
import mineplex.game.clans.items.generation.WeightSet;
import mineplex.game.clans.items.legendaries.AlligatorsTooth;
import mineplex.game.clans.items.legendaries.WindBlade;
public enum ItemType
{
LEGENDARY,
ARMOUR,
WEAPON,
BOW;
}

View File

@ -3,6 +3,9 @@ package mineplex.game.clans.items;
import java.util.HashSet;
import java.util.Set;
import mineplex.game.clans.items.legendaries.LegendaryItem;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@ -36,6 +39,30 @@ public class PlayerGear
{
_playerName = playerName;
}
/**
* Tick & update internal logic for the PlayerGear and required custom items that are
* equipped.
*/
public void update()
{
if (isOnline())
{
CustomItem item = getWeapon();
if (item != null && item instanceof LegendaryItem)
{
LegendaryItem legendary = (LegendaryItem) item;
legendary.update(getPlayer());
}
}
}
public boolean isOnline()
{
Player player = getPlayer();
return player != null && player.isOnline();
}
/**
* @return the {@link Player} that owns this gear set.
@ -69,7 +96,7 @@ public class PlayerGear
* Trigger on-attack events for the set of equipped {@link CustomItem}s in gear set.
* @param event - the triggering on-attack event
*/
public void onAttack(EntityDamageByEntityEvent event)
public void onAttack(CustomDamageEvent event)
{
for (CustomItem item : getGear())
{
@ -81,7 +108,7 @@ public class PlayerGear
* Trigger attacked events for the set of equipped {@link CustomItem}s in gear set.
* @param event - the triggering attacked event
*/
public void onAttacked(EntityDamageByEntityEvent event)
public void onAttacked(CustomDamageEvent event)
{
for (CustomItem item : getGear())
{

View File

@ -1,6 +1,7 @@
package mineplex.game.clans.items.attributes;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
@ -30,12 +31,12 @@ public abstract class ItemAttribute
// Implementation left to subclasses.
}
public void onAttack(EntityDamageByEntityEvent event)
public void onAttack(CustomDamageEvent event)
{
// Implementation left to subclasses.
}
public void onAttacked(EntityDamageByEntityEvent event)
public void onAttacked(CustomDamageEvent event)
{
// Implementation left to subclasses.
}

View File

@ -6,8 +6,7 @@ import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
public class LavaAttribute extends PercentReductionAttribute
{
// TODO: Replace with your generators
{
private static ValueDistribution reductionGen = generateDistribution(0.2d, 1.0d); // Value generator for heal amount
private static ReductionConfig lavaConfig = new ReductionConfig(DamageCause.FIRE, DamageCause.LAVA, DamageCause.FIRE_TICK);

View File

@ -6,8 +6,7 @@ import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
public class PaddedAttribute extends FlatReductionAttribute
{
// TODO: Replace with your generators
{
private static ValueDistribution reductionGen = generateDistribution(1.0d, 4.0d);
private static ReductionConfig config = new ReductionConfig(DamageCause.FALL);

View File

@ -9,7 +9,6 @@ import mineplex.game.clans.items.generation.ValueDistribution;
// A.K.A Conquering for Armor
public class ProtectionAttribute extends FlatReductionAttribute
{
// TODO: Replace with your generators
private static ValueDistribution reductionGen = generateDistribution(1.0d, 4.0d);
private static ReductionConfig config = new ReductionConfig(EntityType.values());

View File

@ -10,6 +10,7 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
public abstract class ReductionAttribute extends ItemAttribute
{
@ -22,18 +23,16 @@ public abstract class ReductionAttribute extends ItemAttribute
}
@Override
public void onAttacked(EntityDamageByEntityEvent event)
public void onAttacked(CustomDamageEvent event)
{
DamageCause cause = event.getCause();
Entity attacker = event.getDamager();
DamageCause cause = event.GetCause();
Entity attacker = event.GetDamagerEntity(true);
if (_config.reducesDamage(cause, attacker))
{
double damage = event.getDamage();
double damage = event.GetDamage();
double reduction = getDamageReduction(damage);
double reducedDamage = Math.max(0, damage - reduction);
event.setDamage(reducedDamage);
event.AddMod("Reduction Armor", reduction);
}
}

View File

@ -6,7 +6,6 @@ import mineplex.game.clans.items.generation.ValueDistribution;
public class ReinforcedAttribute extends FlatReductionAttribute
{
// TODO: Replace with your generators
private static ValueDistribution reductionGen = generateDistribution(0.5d, 1.0d);
private static ReductionConfig config = new ReductionConfig(DamageCause.ENTITY_ATTACK);

View File

@ -7,7 +7,6 @@ import mineplex.game.clans.items.generation.ValueDistribution;
public class SlantedAttribute extends FlatReductionAttribute
{
// TODO: Replace with your generators
private static ValueDistribution reductionGen = generateDistribution(0.5d, 1.5d);
private static ReductionConfig config = new ReductionConfig(DamageCause.PROJECTILE);

View File

@ -7,8 +7,7 @@ import org.bukkit.entity.Player;
public class ConqueringAttribute extends DamageAttribute
{
// TODO: Replace with your generators
private static ValueDistribution damageGen = generateDistribution(1.0d, 6.0d); // Value generator for heal amount
private static ValueDistribution damageGen = generateDistribution(1.0d, 6.0d);
public ConqueringAttribute()
{
@ -18,7 +17,7 @@ public class ConqueringAttribute extends DamageAttribute
@Override
public String getDisplayName()
{
return "Conquering"; // TODO: Fill in name
return "Conquering";
}
@Override

View File

@ -2,6 +2,7 @@ package mineplex.game.clans.items.attributes.weapon;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@ -17,11 +18,11 @@ public abstract class DamageAttribute extends ItemAttribute
}
@Override
public void onAttack(EntityDamageByEntityEvent event)
public void onAttack(CustomDamageEvent event)
{
if (grantBonusDamage(event.getEntity()))
if (grantBonusDamage(event.GetDamageeEntity()))
{
event.setDamage(event.getDamage() + _bonusDamage);
event.AddMod("Damage Attribute", _bonusDamage);
}
}

View File

@ -6,9 +6,8 @@ import org.bukkit.entity.Entity;
public class FlamingAttribute extends AttackAttribute
{
// TODO: Replace with your generators
private static ValueDistribution attackGen = generateDistribution(2, 4); // Value generator for heal amount
private static ValueDistribution fireGen = generateDistribution(60, 120); // Value generator for heal amount
private static ValueDistribution attackGen = generateDistribution(2, 4);
private static ValueDistribution fireGen = generateDistribution(60, 120);
private int _fireDuration;

View File

@ -2,6 +2,7 @@ package mineplex.game.clans.items.attributes.weapon;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@ -44,13 +45,13 @@ public class FrostedAttribute extends ItemAttribute
}
@Override
public void onAttacked(EntityDamageByEntityEvent event)
public void onAttacked(CustomDamageEvent event)
{
if (event.getDamager() instanceof Player)
Player damager = event.GetDamagerPlayer(true);
if (damager != null)
{
Player player = (Player) event.getDamager();
player.addPotionEffect(generateSlowEffect()); // Slow attacking player
damager.addPotionEffect(generateSlowEffect()); // Slow attacking player
}
}

View File

@ -10,10 +10,9 @@ import org.bukkit.util.Vector;
public class HasteAttribute extends AttackAttribute
{
// TODO: Replace with your generators
private static ValueDistribution attackGen = generateDistribution(2, 4); // Value generator for heal amount
private static ValueDistribution speedGen = generateDistribution(0, 2); // Value generator for heal amount
private static ValueDistribution durationGen = generateDistribution(60, 120); // Value generator for heal amount
private static ValueDistribution attackGen = generateDistribution(2, 4);
private static ValueDistribution speedGen = generateDistribution(0, 2);
private static ValueDistribution durationGen = generateDistribution(60, 120);
private int _speedAmount;
private int _speedDuration;
@ -29,7 +28,7 @@ public class HasteAttribute extends AttackAttribute
@Override
public String getDisplayName()
{
return "Haste"; // TODO: Fill in name
return "Haste";
}
@Override

View File

@ -7,8 +7,7 @@ import org.bukkit.util.Vector;
public class JaggedAttribute extends AttackAttribute
{
// TODO: Replace with your generators
private static ValueDistribution attackGen = generateDistribution(2, 4); // Value generator for heal amount
private static ValueDistribution attackGen = generateDistribution(2, 4);
public JaggedAttribute()
{
@ -18,7 +17,7 @@ public class JaggedAttribute extends AttackAttribute
@Override
public String getDisplayName()
{
return "Jagged"; // TODO: Fill in name
return "Jagged";
}
@Override

View File

@ -6,8 +6,7 @@ import org.bukkit.entity.Entity;
public class SharpAttribute extends DamageAttribute
{
// TODO: Replace with your generators
private static ValueDistribution damageGen = generateDistribution(0.5d, 1.5d); // Value generator for heal amount\
private static ValueDistribution damageGen = generateDistribution(0.5d, 1.5d);
public SharpAttribute()
{
@ -17,7 +16,7 @@ public class SharpAttribute extends DamageAttribute
@Override
public String getDisplayName()
{
return "Sharp"; // TODO: Fill in name
return "Sharp";
}
@Override

View File

@ -2,14 +2,14 @@ package mineplex.game.clans.items.attributes.weapon;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
public class VampiricAttribute extends ItemAttribute
{
// TODO: Replace with your generators
private static ValueDistribution healGen = generateDistribution(4, 12); // Value generator for heal amount
private static ValueDistribution healGen = generateDistribution(4, 12);
private int _healPercent;
@ -21,7 +21,7 @@ public class VampiricAttribute extends ItemAttribute
@Override
public String getDisplayName()
{
return "Vampiric"; // TODO: Fill in name
return "Vampiric";
}
@Override
@ -31,17 +31,17 @@ public class VampiricAttribute extends ItemAttribute
}
@Override
public void onAttack(EntityDamageByEntityEvent event)
public void onAttack(CustomDamageEvent event)
{
if (event.getDamager() instanceof Player)
{
Player attacker = (Player) event.getDamager();
double damage = event.getDamage();
double healAmount = damage * (_healPercent / 100d);
double currentHealth = attacker.getHealth();
attacker.setHealth(currentHealth + healAmount);
}
Player damager = event.GetDamagerPlayer(true);
double damage = event.GetDamage();
double healAmount = damage * (_healPercent / 100d);
heal(damager, healAmount);
}
private void heal(Player player, double healAmount)
{
player.setHealth(player.getHealth() + healAmount);
}
}

View File

@ -8,6 +8,7 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector;
import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank;
@ -36,9 +37,13 @@ import mineplex.game.clans.items.legendaries.WindBlade;
public class GearCommand extends CommandBase<GearManager>
{
private GearManager _gearManager;
public GearCommand(GearManager plugin)
{
super(plugin, Rank.ALL, "gear", "custom-gear");
_gearManager = plugin;
}
@Override
@ -46,31 +51,16 @@ public class GearCommand extends CommandBase<GearManager>
{
UtilPlayer.message(caller, F.main("Gear", "Opening custom gear GUI!"));
if (caller.getItemInHand() != null && caller.getItemInHand().getType() != Material.AIR)
if (args == null || args.length == 0)
{
ItemStack item = caller.getItemInHand();
ItemMeta meta = item.getItemMeta();
List<String> lore = meta.getLore();
lore.set(0, "Test");
meta.setLore(lore);
item.setItemMeta(meta);
System.out.println("aaaaaaa");
return;
Vector direction = caller.getLocation().getDirection().normalize();
_gearManager.spawnItem(caller.getEyeLocation().add(direction));
}
else
{
LegendaryItem legendary = new WindBlade();
caller.setItemInHand(legendary.toItemStack(1));
return;
Vector direction = caller.getLocation().getDirection().normalize();
_gearManager.spawnItem(caller.getEyeLocation().add(direction));
}
/*CustomItem customItem = new CustomItem();
customItem.setPrefix(new FrostedAttribute());
customItem.setSuperPrefix(new SharpAttribute());
customItem.setSuffix(new FlamingAttribute());
ItemStack sword = customItem.toItemStack(1);
caller.setItemInHand(sword);*/
// TODO: Open custom gear GUI here
}
}

View File

@ -1,5 +1,6 @@
package mineplex.game.clans.items.generation;
import java.util.Collection;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
@ -11,10 +12,15 @@ public class WeightSet<T>
private Set<Weight<T>> _weights;
private WeightSet()
{
_weights = new HashSet<Weight<T>>();
}
@SafeVarargs
public WeightSet(Weight<T>... weights)
{
_weights = new HashSet<Weight<T>>();
this();
for (Weight<T> weight : weights)
{
@ -22,6 +28,27 @@ public class WeightSet<T>
}
}
@SafeVarargs
public WeightSet(T... elements)
{
this();
for (T element : elements)
{
_weights.add(new Weight<T>(1, element)); // Constant weight of 1 means all elements are equally likely
}
}
public WeightSet(Collection<T> elements)
{
this();
for (T element : elements)
{
_weights.add(new Weight<T>(1, element)); // Constant weight of 1 means all elements are equally likely
}
}
private int getTotalWeight()
{
int total = 0;
@ -52,4 +79,16 @@ public class WeightSet<T>
// Should never reach here.
return null;
}
public Set<T> elements()
{
Set<T> elements = new HashSet<T>();
for (Weight<T> weight : _weights)
{
elements.add(weight.getValue());
}
return elements;
}
}

View File

@ -2,6 +2,7 @@ package mineplex.game.clans.items.legendaries;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@ -35,12 +36,12 @@ public class AlligatorsTooth extends LegendaryItem
}
@Override
public void onAttack(EntityDamageByEntityEvent event, Player wielder)
public void onAttack(CustomDamageEvent event, Player wielder)
{
if (isInWater(wielder))
{
double newDamage = event.getDamage() + _damageBonus;
event.setDamage(newDamage);
event.AddMod("Alligators Tooth", _damageBonus);
event.AddKnockback("Alligators Tooth", 0.5d);
}
super.onAttack(event);
@ -55,6 +56,6 @@ public class AlligatorsTooth extends LegendaryItem
private boolean isInWater(Player player)
{
return true; // TODO: Determine whether player is submerged in water
return player.getLocation().getBlock().isLiquid();
}
}

View File

@ -3,6 +3,8 @@ package mineplex.game.clans.items.legendaries;
import java.util.HashSet;
import java.util.Set;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@ -27,15 +29,11 @@ public class GiantsBroadsword extends LegendaryItem
}
@Override
public void onAttack(EntityDamageByEntityEvent event, Player wielder)
public void onAttack(CustomDamageEvent event, Player wielder)
{
// TODO: Buff knockback and damage values (What are specific values?)
// Chiss: Make 'em up
double bonusDamage = 2.0d; // Too much?
event.setDamage(event.getDamage() + bonusDamage);
// TODO: Apply knockback bonus using previous Clans Custom combat events
event.AddMod("Giants Bonus", bonusDamage);
event.AddKnockback("Giants Sword", 0.5d);
}
private void buffPlayer(Player player)

View File

@ -1,7 +1,9 @@
package mineplex.game.clans.items.legendaries;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.potion.PotionEffect;
@ -9,16 +11,22 @@ import org.bukkit.potion.PotionEffectType;
public class HyperBlade extends LegendaryItem
{
public static final long ATTACK_RATE_DURATION = 100;
private static ValueDistribution amountGen = generateDistribution(0, 3); // [1, 4] speed amount
private static ValueDistribution durationGen = generateDistribution(80, 320); // [4, 16] seconds speed duration
private int _speedAmount;
private int _speedDuration;
private long _lastAttack;
public long timeSinceLastAttack() { return System.currentTimeMillis() - _lastAttack; }
public HyperBlade()
{
super("Hyper Blade", "Increased attack speed!", Material.STICK);
_speedAmount = amountGen.generateIntValue();
_speedDuration = durationGen.generateIntValue();
_lastAttack = 0;
}
@Override
@ -31,15 +39,20 @@ public class HyperBlade extends LegendaryItem
}
@Override
public void onAttack(EntityDamageByEntityEvent event, Player wielder)
public void onAttack(CustomDamageEvent event, Player wielder)
{
// TODO: Reduce after-attack cooldown against players to 100ms (instead of 400ms)
if (timeSinceLastAttack() >= ATTACK_RATE_DURATION)
{
event.SetIgnoreRate(true);
log("Ignoring rate!");
}
}
private void buffPlayer(Player wielder)
{
// Give player speed buff
wielder.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, _speedAmount, _speedDuration));
wielder.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, _speedDuration, _speedAmount));
log("Buffing");
}
private boolean canBuff()

View File

@ -8,6 +8,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
import mineplex.game.clans.items.CustomItem;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
public class LegendaryItem extends CustomItem
{
@ -17,12 +18,6 @@ public class LegendaryItem extends CustomItem
private long _lastBlock; // Timestamp of last block from wielder
public long timeSinceLastBlock() { return System.currentTimeMillis() - _lastBlock; }
public LegendaryItem()
{
this(null, null, null); // TODO: Never used, just to skip base implementation for testing.
}
public LegendaryItem(String name, String description, Material material)
{
super(name, description, material);
@ -35,19 +30,17 @@ public class LegendaryItem extends CustomItem
// Leave implementation to potential subtypes
}
public void onAttack(EntityDamageByEntityEvent event, Player wielder)
public void onAttack(CustomDamageEvent event, Player wielder)
{
// Leave implementation to potential subtypes
}
@Override
public void onAttack(EntityDamageByEntityEvent event)
public void onAttack(CustomDamageEvent event)
{
if (event.getDamager() instanceof Player)
if (event.GetDamagerPlayer(true) != null)
{
Player wielder = (Player) event.getDamager();
onAttack(event, wielder);
onAttack(event, event.GetDamagerPlayer(true));
}
super.onAttack(event);
@ -70,6 +63,11 @@ public class LegendaryItem extends CustomItem
return timeSinceLastBlock() <= BLOCK_COOLDOWN;
}
protected void log(String message)
{
System.out.println("[Custom Item - " + _displayName + "] " + message);
}
/**
* @param minValue - the minimum value for attribute value range
* @param maxValue - the maximum value for attribute value range

View File

@ -1,14 +1,24 @@
package mineplex.game.clans.items.legendaries;
import mineplex.core.common.util.UtilAction;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilMath;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.util.Vector;
public class MagneticBlade extends LegendaryItem
{
public static final double PULL_RANGE = 10d;
public MagneticBlade()
{
super("Magnetic Blade", "Pull enemies closer with special abilities!", Material.STICK);
}
@Override
@ -21,14 +31,32 @@ public class MagneticBlade extends LegendaryItem
}
@Override
public void onAttack(EntityDamageByEntityEvent event, Player wielder)
public void onAttack(CustomDamageEvent event, Player wielder)
{
event.AddKnockback("Magnetic Blade", -0.5d); // Pull players with negative knockback
log("Negative knockback!");
// TODO: Apply negative knockback with [???] velocity/power to victims of attacks
}
private void pullPlayers(Player player)
{
// TODO: Grab all players in line of sight and pull towards player with ??? velocity
{
log("Pulling players!");
Vector direction = player.getLocation().getDirection().normalize().multiply(10.0d);
Location target = player.getEyeLocation().add(direction);
double targetDistance = player.getLocation().distance(target);
for (Player other : player.getWorld().getPlayers())
{
double otherDistance = player.getLocation().distance(other.getLocation());
double otherTargetDistance = target.distance(other.getLocation());
// If player is in-front of us and within pulling range
if (otherTargetDistance < targetDistance && otherDistance <= PULL_RANGE)
{
UtilAction.velocity(other, UtilAlg.getTrajectory(other, player), 0.3, false, 0, 0, 1, true);
}
}
}
private boolean canPull()

View File

@ -3,6 +3,7 @@ package mineplex.game.clans.items.legendaries;
import mineplex.game.clans.items.attributes.ItemAttribute;
import mineplex.game.clans.items.generation.ValueDistribution;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@ -15,6 +16,7 @@ public class MeteorBow extends LegendaryItem
public MeteorBow()
{
super("Meteor Bow", "Shoot explosive arrows!", Material.BOW);
_flightTime = 0;
}

View File

@ -12,7 +12,7 @@ import org.bukkit.util.Vector;
public class WindBlade extends LegendaryItem
{
public static final double FLIGHT_VELOCITY = 0.25d;
public static final double FLIGHT_VELOCITY = 0.75d;
public static final int MAX_FLIGHT_TIME = 80; // Max flight of 80 ticks
private long _flightTime; // Time (in ticks) since last touching ground and flying

View File

@ -91,6 +91,10 @@ public class CustomDamageEvent extends Event implements Cancellable
_damageMult.add(new DamageChange(source, reason, mod, useAttackName));
}
public void AddMod(String source, double mod)
{
AddMod(source, new String(), mod, false);
}
public void AddMod(String source, String reason, double mod, boolean useAttackName)
{

View File

@ -215,25 +215,29 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
}
@Override public void write(JsonWriter out, R value) throws IOException {
Class<?> srcType = value.getClass();
String label = subtypeToLabel.get(srcType);
@SuppressWarnings("unchecked") // registration requires that subtype extends T
TypeAdapter<R> delegate = (TypeAdapter<R>) subtypeToDelegate.get(srcType);
if (delegate == null) {
throw new JsonParseException("cannot serialize " + srcType.getName()
+ "; did you forget to register a subtype?");
}
JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject();
if (jsonObject.has(typeFieldName)) {
throw new JsonParseException("cannot serialize " + srcType.getName()
+ " because it already defines a field named " + typeFieldName);
}
JsonObject clone = new JsonObject();
clone.add(typeFieldName, new JsonPrimitive(label));
for (Map.Entry<String, JsonElement> e : jsonObject.entrySet()) {
clone.add(e.getKey(), e.getValue());
}
Streams.write(clone, out);
if(value!=null) {
Class<?> srcType = value.getClass();
String label = subtypeToLabel.get(srcType);
@SuppressWarnings("unchecked") // registration requires that subtype extends T
TypeAdapter<R> delegate = (TypeAdapter<R>) subtypeToDelegate.get(srcType);
if (delegate == null) {
throw new JsonParseException("cannot serialize " + srcType.getName()
+ "; did you forget to register a subtype?");
}
JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject();
if (jsonObject.has(typeFieldName)) {
throw new JsonParseException("cannot serialize " + srcType.getName()
+ " because it already defines a field named " + typeFieldName);
}
JsonObject clone = new JsonObject();
clone.add(typeFieldName, new JsonPrimitive(label));
for (Map.Entry<String, JsonElement> e : jsonObject.entrySet()) {
clone.add(e.getKey(), e.getValue());
}
Streams.write(clone, out);
}else{
out.nullValue();
}
}
};
}