2012-04-27 11:47:11 +02:00
package com.gmail.nossr50.util ;
2019-01-15 07:11:58 +01:00
import com.gmail.nossr50.events.items.McMMOItemSpawnEvent ;
import com.gmail.nossr50.mcMMO ;
import com.gmail.nossr50.runnables.player.PlayerProfileLoadingTask ;
import com.gmail.nossr50.util.player.UserManager ;
import com.google.common.collect.ImmutableSet ;
2012-04-27 11:47:11 +02:00
import org.bukkit.Location ;
import org.bukkit.Material ;
2016-03-16 17:47:40 +01:00
import org.bukkit.block.BlockState ;
2019-04-05 03:55:25 +02:00
import org.bukkit.entity.* ;
2012-04-27 11:47:11 +02:00
import org.bukkit.inventory.ItemStack ;
2019-06-21 17:05:57 +02:00
import org.bukkit.util.Vector ;
2012-04-27 11:47:11 +02:00
2019-01-15 07:11:58 +01:00
import java.util.Collection ;
import java.util.Random ;
import java.util.Set ;
2014-08-31 19:10:49 +02:00
2013-01-26 23:01:55 +01:00
public final class Misc {
2012-04-27 11:47:11 +02:00
private static Random random = new Random ( ) ;
2013-06-13 01:26:09 +02:00
2013-01-10 03:44:53 +01:00
public static final int TIME_CONVERSION_FACTOR = 1000 ;
2013-06-13 01:26:09 +02:00
public static final int TICK_CONVERSION_FACTOR = 20 ;
public static final int PLAYER_RESPAWN_COOLDOWN_SECONDS = 5 ;
2013-01-10 03:44:53 +01:00
public static final double SKILL_MESSAGE_MAX_SENDING_DISTANCE = 10 . 0 ;
2013-03-01 06:52:01 +01:00
// Sound Pitches & Volumes from CB
2019-01-13 04:08:54 +01:00
/ * public static final float ANVIL_USE_PITCH = 0 . 3F ; // Not in CB directly, I went off the place sound values
2016-03-06 22:48:22 +01:00
public static final float ANVIL_USE_VOLUME = 1 . 0F * Config . getInstance ( ) . getMasterVolume ( ) ; // Not in CB directly, I went off the place sound values
public static final float FIZZ_VOLUME = 0 . 5F * Config . getInstance ( ) . getMasterVolume ( ) ;
public static final float POP_VOLUME = 0 . 2F * Config . getInstance ( ) . getMasterVolume ( ) ;
public static final float BAT_VOLUME = 1 . 0F * Config . getInstance ( ) . getMasterVolume ( ) ;
2013-03-14 22:26:02 +01:00
public static final float BAT_PITCH = 0 . 6F ;
2016-03-06 22:48:22 +01:00
public static final float GHAST_VOLUME = 1 . 0F * Config . getInstance ( ) . getMasterVolume ( ) ;
2013-09-16 15:52:09 +02:00
public static final float LEVELUP_PITCH = 0 . 5F ; // Reduced to differentiate between vanilla level-up
2019-01-13 04:08:54 +01:00
public static final float LEVELUP_VOLUME = 0 . 75F * Config . getInstance ( ) . getMasterVolume ( ) ; // Use max volume always*/
2013-01-30 00:36:16 +01:00
2014-08-31 19:10:49 +02:00
public static final Set < String > modNames = ImmutableSet . of ( " LOTR " , " BUILDCRAFT " , " ENDERIO " , " ENHANCEDBIOMES " , " IC2 " , " METALLURGY " , " FORESTRY " , " GALACTICRAFT " , " RAILCRAFT " , " TWILIGHTFOREST " , " THAUMCRAFT " , " GRAVESTONEMOD " , " GROWTHCRAFT " , " ARCTICMOBS " , " DEMONMOBS " , " INFERNOMOBS " , " SWAMPMOBS " , " MARICULTURE " , " MINESTRAPPOLATION " ) ;
2013-01-26 23:01:55 +01:00
private Misc ( ) { } ;
2019-07-05 14:51:41 +02:00
/ * *
* Determines if an entity is an NPC but not a villager
* This method aims to establish compatibility between mcMMO and other plugins which create " NPCs "
*
* It does this by checking the following
* 1 ) The entity is not a Villager
* 2 ) The entity can be considered an NPC
*
* In this context , an NPC is a bit hard to define . Various plugins determine what an NPC is in different ways .
* @see Misc : : isNPCIncludingVillagers
* @param entity target entity
* @return true if the entity is not a Villager and is not a " NPC "
* /
2019-06-17 16:00:39 +02:00
public static boolean isNPCEntityExcludingVillagers ( Entity entity ) {
2019-07-05 14:51:41 +02:00
return ( ! isVillager ( entity )
& & isNPCIncludingVillagers ( entity ) ) ; //Compatibility with some mod..
}
public static boolean isNPCClassType ( Entity entity ) {
return entity instanceof NPC ;
}
public static boolean hasNPCMetadataTag ( Entity entity ) {
return entity . hasMetadata ( " NPC " ) ;
}
public static boolean isVillager ( Entity entity ) {
2019-07-05 15:14:54 +02:00
String entityType = entity . getType ( ) . toString ( ) ;
//This weird code is for 1.13 & 1.14 compatibility
return entityType . equalsIgnoreCase ( " wandering_trader " ) | | entity instanceof Villager ;
2013-01-24 21:46:29 +01:00
}
2019-07-05 14:51:41 +02:00
public static boolean isNPCIncludingVillagers ( Entity entity ) {
2019-06-17 16:00:39 +02:00
return ( entity = = null
2019-07-05 14:51:41 +02:00
| | ( hasNPCMetadataTag ( entity ) )
| | ( isNPCClassType ( entity ) )
2019-06-17 16:00:39 +02:00
| | entity . getClass ( ) . getName ( ) . equalsIgnoreCase ( " cofh.entity.PlayerFake " ) ) ;
}
2012-04-27 11:47:11 +02:00
/ * *
* Determine if two locations are near each other .
*
* @param first The first location
* @param second The second location
* @param maxDistance The max distance apart
2013-08-10 20:10:45 +02:00
* @return true if the distance between { @code first } and { @code second } is less than { @code maxDistance } , false otherwise
2012-04-27 11:47:11 +02:00
* /
public static boolean isNear ( Location first , Location second , double maxDistance ) {
2014-02-27 16:56:21 +01:00
return ( first . getWorld ( ) = = second . getWorld ( ) ) & & ( first . distanceSquared ( second ) < ( maxDistance * maxDistance ) | | maxDistance = = 0 ) ;
2013-05-16 15:23:35 +02:00
}
2013-01-10 04:43:21 +01:00
2016-03-16 21:47:24 +01:00
/ * *
* Get the center of the given block .
*
* @param blockState The { @link BlockState } of the block
* @return A { @link Location } lying at the center of the block
* /
public static Location getBlockCenter ( BlockState blockState ) {
2016-03-17 02:38:24 +01:00
return blockState . getLocation ( ) . add ( 0 . 5 , 0 . 5 , 0 . 5 ) ;
2016-03-16 17:47:40 +01:00
}
2013-05-16 15:23:35 +02:00
public static void dropItems ( Location location , Collection < ItemStack > drops ) {
for ( ItemStack drop : drops ) {
dropItem ( location , drop ) ;
}
2012-04-27 11:47:11 +02:00
}
/ * *
* Drop items at a given location .
*
* @param location The location to drop the items at
* @param is The items to drop
* @param quantity The amount of items to drop
* /
2012-05-18 19:40:21 +02:00
public static void dropItems ( Location location , ItemStack is , int quantity ) {
2012-04-27 11:47:11 +02:00
for ( int i = 0 ; i < quantity ; i + + ) {
2012-05-18 19:40:21 +02:00
dropItem ( location , is ) ;
2012-04-27 11:47:11 +02:00
}
}
/ * *
* Drop an item at a given location .
*
* @param location The location to drop the item at
* @param itemStack The item to drop
2013-12-02 00:43:17 +01:00
* @return Dropped Item entity or null if invalid or cancelled
2012-04-27 11:47:11 +02:00
* /
2013-12-02 00:43:17 +01:00
public static Item dropItem ( Location location , ItemStack itemStack ) {
2013-02-03 09:12:34 +01:00
if ( itemStack . getType ( ) = = Material . AIR ) {
2013-12-02 00:43:17 +01:00
return null ;
2013-02-01 20:58:03 +01:00
}
2013-01-14 20:31:11 +01:00
2012-04-27 11:47:11 +02:00
// We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event.
McMMOItemSpawnEvent event = new McMMOItemSpawnEvent ( location , itemStack ) ;
2012-06-07 00:02:22 +02:00
mcMMO . p . getServer ( ) . getPluginManager ( ) . callEvent ( event ) ;
2012-04-27 11:47:11 +02:00
2013-03-01 06:52:01 +01:00
if ( event . isCancelled ( ) ) {
2013-12-02 00:43:17 +01:00
return null ;
2013-03-01 06:52:01 +01:00
}
2012-04-27 11:47:11 +02:00
2018-12-15 01:51:38 +01:00
return location . getWorld ( ) . dropItem ( location , itemStack ) ;
2012-04-27 11:47:11 +02:00
}
2019-06-21 17:05:57 +02:00
/ * *
* Drop items at a given location .
*
2019-06-26 03:02:16 +02:00
* @param fromLocation The location to drop the items at
2019-06-21 17:05:57 +02:00
* @param is The items to drop
2019-06-26 03:02:16 +02:00
* @param speed the speed that the item should travel
2019-06-21 17:05:57 +02:00
* @param quantity The amount of items to drop
* /
2019-06-26 03:02:16 +02:00
public static void spawnItemsTowardsLocation ( Location fromLocation , Location toLocation , ItemStack is , int quantity , double speed ) {
2019-06-21 17:05:57 +02:00
for ( int i = 0 ; i < quantity ; i + + ) {
2019-06-26 03:02:16 +02:00
spawnItemTowardsLocation ( fromLocation , toLocation , is , speed ) ;
2019-06-21 17:05:57 +02:00
}
}
/ * *
* Drop an item at a given location .
2019-06-26 03:02:16 +02:00
* This method is fairly expensive as it creates clones of everything passed to itself since they are mutable objects
2019-06-21 17:05:57 +02:00
*
2019-06-26 03:02:16 +02:00
* @param fromLocation The location to drop the item at
* @param toLocation The location the item will travel towards
* @param itemToSpawn The item to spawn
* @param speed the speed that the item should travel
2019-06-21 17:05:57 +02:00
* @return Dropped Item entity or null if invalid or cancelled
* /
2019-06-26 03:02:16 +02:00
public static Item spawnItemTowardsLocation ( Location fromLocation , Location toLocation , ItemStack itemToSpawn , double speed ) {
if ( itemToSpawn . getType ( ) = = Material . AIR ) {
2019-06-21 17:05:57 +02:00
return null ;
}
2019-06-26 03:02:16 +02:00
//Work with fresh copies of everything
ItemStack clonedItem = itemToSpawn . clone ( ) ;
Location spawnLocation = fromLocation . clone ( ) ;
Location targetLocation = toLocation . clone ( ) ;
2019-06-21 17:05:57 +02:00
// We can't get the item until we spawn it and we want to make it cancellable, so we have a custom event.
2019-06-26 03:02:16 +02:00
McMMOItemSpawnEvent event = new McMMOItemSpawnEvent ( spawnLocation , clonedItem ) ;
2019-06-21 17:05:57 +02:00
mcMMO . p . getServer ( ) . getPluginManager ( ) . callEvent ( event ) ;
2019-06-26 03:02:16 +02:00
//Something cancelled the event so back out
if ( event . isCancelled ( ) | | event . getItemStack ( ) = = null ) {
2019-06-21 17:05:57 +02:00
return null ;
}
2019-06-26 03:02:16 +02:00
//Use the item from the event
Item spawnedItem = spawnLocation . getWorld ( ) . dropItem ( spawnLocation , clonedItem ) ;
Vector vecFrom = spawnLocation . clone ( ) . toVector ( ) . clone ( ) ;
Vector vecTo = targetLocation . clone ( ) . toVector ( ) . clone ( ) ;
//Vector which is pointing towards out target location
Vector direction = vecTo . subtract ( vecFrom ) . normalize ( ) ;
//Modify the speed of the vector
direction = direction . multiply ( speed ) ;
spawnedItem . setVelocity ( direction ) ;
return spawnedItem ;
2019-06-21 17:05:57 +02:00
}
2013-03-12 21:25:42 +01:00
public static void profileCleanup ( String playerName ) {
2013-09-16 18:12:31 +02:00
Player player = mcMMO . p . getServer ( ) . getPlayerExact ( playerName ) ;
if ( player ! = null ) {
2014-02-07 18:50:04 +01:00
UserManager . remove ( player ) ;
2014-08-06 05:02:41 +02:00
new PlayerProfileLoadingTask ( player ) . runTaskLaterAsynchronously ( mcMMO . p , 1 ) ; // 1 Tick delay to ensure the player is marked as online before we begin loading
2013-03-12 21:25:42 +01:00
}
}
2013-10-18 16:43:37 +02:00
public static void printProgress ( int convertedUsers , int progressInterval , long startMillis ) {
if ( ( convertedUsers % progressInterval ) = = 0 ) {
2013-12-10 23:56:07 +01:00
mcMMO . p . getLogger ( ) . info ( String . format ( " Conversion progress: %d users at %.2f users/second " , convertedUsers , convertedUsers / ( double ) ( ( System . currentTimeMillis ( ) - startMillis ) / TIME_CONVERSION_FACTOR ) ) ) ;
2013-10-18 16:43:37 +02:00
}
}
2014-08-31 19:10:49 +02:00
public static String getModName ( String materialName ) {
for ( String mod : modNames ) {
if ( materialName . contains ( mod ) ) {
return mod ;
}
}
String [ ] materialSplit = materialName . split ( " _ " ) ;
if ( materialSplit . length > 1 ) {
return materialSplit [ 0 ] . toLowerCase ( ) ;
}
return " UnknownMods " ;
}
2014-12-20 19:11:08 +01:00
/ * *
* Gets a random location near the specified location
* /
public static Location getLocationOffset ( Location location , double strength ) {
double blockX = location . getBlockX ( ) ;
double blockZ = location . getBlockZ ( ) ;
double distance ;
distance = strength * random . nextDouble ( ) ;
blockX = ( random . nextBoolean ( ) ) ? blockX + ( distance ) : blockX - ( distance ) ;
distance = strength * random . nextDouble ( ) ;
blockZ = ( random . nextBoolean ( ) ) ? blockZ + ( distance ) : blockZ - ( distance ) ;
return new Location ( location . getWorld ( ) , blockX , location . getY ( ) , blockZ ) ;
}
2013-01-10 05:46:35 +01:00
public static Random getRandom ( ) {
return random ;
}
2012-04-27 11:47:11 +02:00
}