private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions) { EntityDamageEvent event; if (damager != null) { event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, modifiers, modifierFunctions); } else { event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, modifiers, modifierFunctions); } callEvent(event); if (!event.isCancelled()) { event.getEntity().setLastDamageCause(event); } return event; }
public static EntityDamageEvent handleLivingEntityDamageEvent(Entity damagee, DamageSource source, double rawDamage, double hardHatModifier, double blockingModifier, double armorModifier, double resistanceModifier, double magicModifier, double absorptionModifier, Function<Double, Double> hardHat, Function<Double, Double> blocking, Function<Double, Double> armor, Function<Double, Double> resistance, Function<Double, Double> magic, Function<Double, Double> absorption) { Map<DamageModifier, Double> modifiers = new EnumMap<DamageModifier, Double>(DamageModifier.class); Map<DamageModifier, Function<? super Double, Double>> modifierFunctions = new EnumMap<DamageModifier, Function<? super Double, Double>>(DamageModifier.class); modifiers.put(DamageModifier.BASE, rawDamage); modifierFunctions.put(DamageModifier.BASE, ZERO); if (source == DamageSource.FALLING_BLOCK || source == DamageSource.ANVIL) { modifiers.put(DamageModifier.HARD_HAT, hardHatModifier); modifierFunctions.put(DamageModifier.HARD_HAT, hardHat); } if (damagee instanceof EntityHuman) { modifiers.put(DamageModifier.BLOCKING, blockingModifier); modifierFunctions.put(DamageModifier.BLOCKING, blocking); } modifiers.put(DamageModifier.ARMOR, armorModifier); modifierFunctions.put(DamageModifier.ARMOR, armor); modifiers.put(DamageModifier.RESISTANCE, resistanceModifier); modifierFunctions.put(DamageModifier.RESISTANCE, resistance); modifiers.put(DamageModifier.MAGIC, magicModifier); modifierFunctions.put(DamageModifier.MAGIC, magic); modifiers.put(DamageModifier.ABSORPTION, absorptionModifier); modifierFunctions.put(DamageModifier.ABSORPTION, absorption); return handleEntityDamageEvent(damagee, source, modifiers, modifierFunctions); }
public static boolean handleNonLivingEntityDamageEvent(Entity entity, DamageSource source, double damage, boolean cancelOnZeroDamage) { if (entity instanceof EntityEnderCrystal && !(source instanceof EntityDamageSource)) { return false; } final EnumMap<DamageModifier, Double> modifiers = new EnumMap<DamageModifier, Double>(DamageModifier.class); final EnumMap<DamageModifier, Function<? super Double, Double>> functions = new EnumMap(DamageModifier.class); modifiers.put(DamageModifier.BASE, damage); functions.put(DamageModifier.BASE, ZERO); final EntityDamageEvent event = handleEntityDamageEvent(entity, source, modifiers, functions); if (event == null) { return false; } return event.isCancelled() || (cancelOnZeroDamage && event.getDamage() == 0); }
public static BlockIgniteEvent callBlockIgniteEvent(World world, int x, int y, int z, Entity igniter) { org.bukkit.World bukkitWorld = world.getWorld(); org.bukkit.entity.Entity bukkitIgniter = igniter.getBukkitEntity(); IgniteCause cause; switch (bukkitIgniter.getType()) { case ENDER_CRYSTAL: cause = IgniteCause.ENDER_CRYSTAL; break; case LIGHTNING: cause = IgniteCause.LIGHTNING; break; case SMALL_FIREBALL: case FIREBALL: cause = IgniteCause.FIREBALL; break; default: cause = IgniteCause.FLINT_AND_STEEL; } BlockIgniteEvent event = new BlockIgniteEvent(bukkitWorld.getBlockAt(x, y, z), cause, bukkitIgniter); world.getServer().getPluginManager().callEvent(event); return event; }
/** * EntityDamage(ByEntityEvent) */ public static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, double damage) { EntityDamageEvent event; if (damager != null) { event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, damage); } else { event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, damage); } callEvent(event); if (!event.isCancelled()) { event.getEntity().setLastDamageCause(event); } return event; }
/** * Gets the range an entity should be 'tracked' by players and visible in * the client. * * @param entity * @param defaultRange Default range defined by Mojang * @return */ public static int getEntityTrackingRange(Entity entity, int defaultRange) { SpigotWorldConfig config = entity.world.spigotConfig; int range = defaultRange; if ( entity instanceof EntityPlayer ) { range = config.playerTrackingRange; } else if ( entity.defaultActivationState || entity instanceof EntityGhast ) { range = defaultRange; } else if ( entity.activationType == 1 ) { range = config.monsterTrackingRange; } else if ( entity.activationType == 2 ) { range = config.animalTrackingRange; } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) { range = config.miscTrackingRange; } return Math.min( config.maxTrackingRange, range ); }
/** * These entities are excluded from Activation range checks. * * @param entity * @param world * @return boolean If it should always tick. */ public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) { if ( ( entity.activationType == 3 && config.miscActivationRange == 0 ) || ( entity.activationType == 2 && config.animalActivationRange == 0 ) || ( entity.activationType == 1 && config.monsterActivationRange == 0 ) || entity instanceof EntityHuman || entity instanceof EntityProjectile || entity instanceof EntityEnderDragon || entity instanceof EntityComplexPart || entity instanceof EntityWither || entity instanceof EntityFireball || entity instanceof EntityWeather || entity instanceof EntityTNTPrimed || entity instanceof EntityEnderCrystal || entity instanceof EntityFireworks ) { return true; } return false; }
/** * EntityDamage(ByEntityEvent) */ public static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, int damage) { EntityDamageEvent event; if (damager != null) { event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, damage); } else { event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, damage); } callEvent(event); if (!event.isCancelled()) { event.getEntity().setLastDamageCause(event); } return event; }
/** * EntityTameEvent */ public static EntityTameEvent callEntityTameEvent(EntityInsentient entity, EntityHuman tamer) { org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); org.bukkit.entity.AnimalTamer bukkitTamer = (tamer != null ? tamer.getBukkitEntity() : null); CraftServer craftServer = (CraftServer) bukkitEntity.getServer(); entity.persistent = true; EntityTameEvent event = new EntityTameEvent((LivingEntity) bukkitEntity, bukkitTamer); craftServer.getPluginManager().callEvent(event); return event; }
public static EntityBreakDoorEvent callEntityBreakDoorEvent(Entity entity, int x, int y, int z) { org.bukkit.entity.Entity entity1 = entity.getBukkitEntity(); Block block = entity1.getWorld().getBlockAt(x, y, z); EntityBreakDoorEvent event = new EntityBreakDoorEvent((LivingEntity) entity1, block); entity1.getServer().getPluginManager().callEvent(event); return event; }
public static BlockIgniteEvent callBlockIgniteEvent(World world, int x, int y, int z, Explosion explosion) { org.bukkit.World bukkitWorld = world.getWorld(); org.bukkit.entity.Entity igniter = explosion.source == null ? null : explosion.source.getBukkitEntity(); BlockIgniteEvent event = new BlockIgniteEvent(bukkitWorld.getBlockAt(x, y, z), IgniteCause.EXPLOSION, igniter); world.getServer().getPluginManager().callEvent(event); return event; }
/** * Mob spawner event */ public static SpawnerSpawnEvent callSpawnerSpawnEvent(Entity spawnee, int spawnerX, int spawnerY, int spawnerZ) { org.bukkit.craftbukkit.entity.CraftEntity entity = spawnee.getBukkitEntity(); BlockState state = entity.getWorld().getBlockAt(spawnerX, spawnerY, spawnerZ).getState(); if (!(state instanceof CreatureSpawner)) { state = null; } SpawnerSpawnEvent event = new SpawnerSpawnEvent(entity, (CreatureSpawner) state); entity.getServer().getPluginManager().callEvent(event); return event; }
public static boolean handleNonLivingEntityDamageEvent(Entity entity, DamageSource source, float damage) { if (!(source instanceof EntityDamageSource)) { return false; } // We don't need to check for null, since EntityDamageSource will always return an event EntityDamageEvent event = handleEntityDamageEvent(entity, source, damage); return event.isCancelled() || event.getDamage() == 0; }
/** * Initializes an entities type on construction to specify what group this * entity is in for activation ranges. * * @param entity * @return group id */ public static byte initializeEntityActivationType(Entity entity) { if ( entity instanceof EntityMonster || entity instanceof EntitySlime ) { return 1; // Monster } else if ( entity instanceof EntityCreature || entity instanceof EntityAmbient ) { return 2; // Animal } else { return 3; // Misc } }
/** * Find what entities are in range of the players in the world and set * active if in range. * * @param world */ public static void activateEntities(World world) { SpigotTimings.entityActivationCheckTimer.startTiming(); final int miscActivationRange = world.spigotConfig.miscActivationRange; final int animalActivationRange = world.spigotConfig.animalActivationRange; final int monsterActivationRange = world.spigotConfig.monsterActivationRange; int maxRange = Math.max( monsterActivationRange, animalActivationRange ); maxRange = Math.max( maxRange, miscActivationRange ); maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); for ( Entity player : new ArrayList<Entity>( world.players ) ) { player.activatedTick = MinecraftServer.currentTick; growBB( maxBB, player.boundingBox, maxRange, 256, maxRange ); growBB( miscBB, player.boundingBox, miscActivationRange, 256, miscActivationRange ); growBB( animalBB, player.boundingBox, animalActivationRange, 256, animalActivationRange ); growBB( monsterBB, player.boundingBox, monsterActivationRange, 256, monsterActivationRange ); int i = MathHelper.floor( maxBB.a / 16.0D ); int j = MathHelper.floor( maxBB.d / 16.0D ); int k = MathHelper.floor( maxBB.c / 16.0D ); int l = MathHelper.floor( maxBB.f / 16.0D ); for ( int i1 = i; i1 <= j; ++i1 ) { for ( int j1 = k; j1 <= l; ++j1 ) { if ( world.getWorld().isChunkLoaded( i1, j1 ) ) { activateChunkEntities( world.getChunkAt( i1, j1 ) ); } } } } SpigotTimings.entityActivationCheckTimer.stopTiming(); }
/** * Checks for the activation state of all entities in this chunk. * * @param chunk */ private static void activateChunkEntities(Chunk chunk) { for ( List<Entity> slice : chunk.entitySlices ) { for ( Entity entity : slice ) { if ( MinecraftServer.currentTick > entity.activatedTick ) { if ( entity.defaultActivationState ) { entity.activatedTick = MinecraftServer.currentTick; continue; } switch ( entity.activationType ) { case 1: if ( monsterBB.b( entity.boundingBox ) ) { entity.activatedTick = MinecraftServer.currentTick; } break; case 2: if ( animalBB.b( entity.boundingBox ) ) { entity.activatedTick = MinecraftServer.currentTick; } break; case 3: default: if ( miscBB.b( entity.boundingBox ) ) { entity.activatedTick = MinecraftServer.currentTick; } } } } } }
/** * Checks if the entity is active for this tick. * * @param entity * @return */ public static boolean checkIfActive(Entity entity) { SpigotTimings.checkIfActiveTimer.startTiming(); boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; // Should this entity tick? if ( !isActive ) { if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) { // Check immunities every 20 ticks. if ( checkEntityImmunities( entity ) ) { // Triggered some sort of immunity, give 20 full ticks before we check again. entity.activatedTick = MinecraftServer.currentTick + 20; } isActive = true; } // Add a little performance juice to active entities. Skip 1/4 if not immune. } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) { isActive = false; } int x = MathHelper.floor( entity.locX ); int z = MathHelper.floor( entity.locZ ); // Make sure not on edge of unloaded chunk if ( isActive && !entity.world.areChunksLoaded( x, 0, z, 16 ) ) { isActive = false; } SpigotTimings.checkIfActiveTimer.stopTiming(); return isActive; }
/** * Gets the range an entity should be 'tracked' by players and visible in * the client. * * @param entity * @param defaultRange Default range defined by Mojang * @return */ public static int getEntityTrackingRange(Entity entity, int defaultRange) { SpigotWorldConfig config = entity.world.spigotConfig; if ( entity instanceof EntityPlayer ) { return config.playerTrackingRange; } else if ( entity.activationType == 1 ) { return config.monsterTrackingRange; } else if ( entity instanceof EntityGhast ) { if ( config.monsterTrackingRange > config.monsterActivationRange ) { return config.monsterTrackingRange; } else { return config.monsterActivationRange; } } else if ( entity.activationType == 2 ) { return config.animalTrackingRange; } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) { return config.miscTrackingRange; } else { return config.otherTrackingRange; } }
/** * Find what entities are in range of the players in the world and set * active if in range. * * @param world */ public static void activateEntities(World world) { SpigotTimings.entityActivationCheckTimer.startTiming(); final int miscActivationRange = world.spigotConfig.miscActivationRange; final int animalActivationRange = world.spigotConfig.animalActivationRange; final int monsterActivationRange = world.spigotConfig.monsterActivationRange; int maxRange = Math.max( monsterActivationRange, animalActivationRange ); maxRange = Math.max( maxRange, miscActivationRange ); maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); for ( Entity player : (List<Entity>) world.players ) { player.activatedTick = MinecraftServer.currentTick; growBB( maxBB, player.boundingBox, maxRange, 256, maxRange ); growBB( miscBB, player.boundingBox, miscActivationRange, 256, miscActivationRange ); growBB( animalBB, player.boundingBox, animalActivationRange, 256, animalActivationRange ); growBB( monsterBB, player.boundingBox, monsterActivationRange, 256, monsterActivationRange ); int i = MathHelper.floor( maxBB.a / 16.0D ); int j = MathHelper.floor( maxBB.d / 16.0D ); int k = MathHelper.floor( maxBB.c / 16.0D ); int l = MathHelper.floor( maxBB.f / 16.0D ); for ( int i1 = i; i1 <= j; ++i1 ) { for ( int j1 = k; j1 <= l; ++j1 ) { if ( world.getWorld().isChunkLoaded( i1, j1 ) ) { activateChunkEntities( world.getChunkAt( i1, j1 ) ); } } } } SpigotTimings.entityActivationCheckTimer.stopTiming(); }
/** * Checks if the entity is active for this tick. * * @param entity * @return */ public static boolean checkIfActive(Entity entity) { SpigotTimings.checkIfActiveTimer.startTiming(); boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; // Should this entity tick? if ( !isActive ) { if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) { // Check immunities every 20 ticks. if ( checkEntityImmunities( entity ) ) { // Triggered some sort of immunity, give 20 full ticks before we check again. entity.activatedTick = MinecraftServer.currentTick + 20; } isActive = true; } // Add a little performance juice to active entities. Skip 1/4 if not immune. } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) { isActive = false; } int x = MathHelper.floor( entity.locX ); int z = MathHelper.floor( entity.locZ ); // Make sure not on edge of unloaded chunk Chunk chunk = entity.world.getChunkIfLoaded( x >> 4, z >> 4 ); if ( isActive && !( chunk != null && chunk.areNeighborsLoaded( 1 ) ) ) { isActive = false; } SpigotTimings.checkIfActiveTimer.stopTiming(); return isActive; }
@SuppressWarnings("unchecked") private static <T> DataWatcherObject<T> getDataWatcher(Class<? extends Entity> cl, String field, Class<T> result) { try { Field entryField = cl.getDeclaredField(field); entryField.setAccessible(true); return (DataWatcherObject<T>) entryField.get(null); } catch (Exception e) { e.printStackTrace(); } return null; }
public static List<DataWatcher.Item<?>> getDamageIndicator(double damage) { Class<EntityArmorStand> cl = EntityArmorStand.class; return Lists.newArrayList( INVISIBLE, // (0) Sets invisible new DataWatcher.Item<>(cl, getDataWatcher(Entity.class, "aA", String.class), "" + ChatColor.RED + ChatColor.BOLD + Math.round(damage / 0.2)), // (2) Custom Name new DataWatcher.Item<>(cl, getDataWatcher(Entity.class, "aB", Boolean.class), true),// (3) Custom Name visible new DataWatcher.Item<>(cl, EntityArmorStand.a, (byte) 0x10)); // (11) Marker Armor Stand }