use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class ConversionHandler method createEntityStackNBT.
/**
* Used to fill in the missing entity stack nbt data
*
* @param entityType The type of entity
* @param amount The amount of nbt entries to create
* @param location The location of the main entity
* @return A list of nbt data
*/
protected StackedEntityDataStorage createEntityStackNBT(EntityType entityType, int amount, Location location) {
NMSHandler nmsHandler = NMSAdapter.getHandler();
StackedEntityDataStorage stackedEntityDataStorage = nmsHandler.createEntityDataStorage(nmsHandler.createNewEntityUnspawned(entityType, location, CreatureSpawnEvent.SpawnReason.CUSTOM));
for (int i = 0; i < amount - 1; i++) stackedEntityDataStorage.addFirst(nmsHandler.createNewEntityUnspawned(entityType, location, CreatureSpawnEvent.SpawnReason.CUSTOM));
return stackedEntityDataStorage;
}
use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class StackedEntity method dropPartialStackLoot.
/**
* Drops loot for entities that are part of the stack.
* Does not include loot for the current entity (except for nether stars for withers).
*
* @param internalEntities The entities which should be part of this stack
* @param existingLoot The loot from this.entity, nullable
* @param droppedExp The exp dropped from this.entity
*/
public void dropPartialStackLoot(List<LivingEntity> internalEntities, Collection<ItemStack> existingLoot, int droppedExp) {
// Cache the current entity just in case it somehow changes while we are processing the loot
LivingEntity thisEntity = this.entity;
Collection<ItemStack> loot = new ArrayList<>();
if (existingLoot != null)
loot.addAll(existingLoot);
// The stack loot can either be processed synchronously or asynchronously depending on a setting
// It should always be processed async unless errors are caused by other plugins
boolean async = Setting.ENTITY_DEATH_EVENT_RUN_ASYNC.getBoolean();
boolean multiplyCustomLoot = Setting.ENTITY_MULTIPLY_CUSTOM_LOOT.getBoolean();
Runnable mainTask = () -> {
boolean callEvents = Setting.ENTITY_TRIGGER_DEATH_EVENT_FOR_ENTIRE_STACK_KILL.getBoolean();
int totalExp = droppedExp;
NMSHandler nmsHandler = NMSAdapter.getHandler();
boolean isAnimal = thisEntity instanceof Animals;
boolean isSlime = thisEntity instanceof Slime;
boolean isAccurateSlime = isSlime && ((SlimeStackSettings) this.stackSettings).isAccurateDropsWithKillEntireStackOnDeath();
for (LivingEntity entity : internalEntities) {
// Propagate fire ticks and last damage cause
entity.setFireTicks(thisEntity.getFireTicks());
entity.setLastDamageCause(thisEntity.getLastDamageCause());
nmsHandler.setLastHurtBy(entity, thisEntity.getKiller());
int iterations = 1;
if (isSlime) {
Slime slime = (Slime) entity;
if (isAccurateSlime) {
int totalSlimes = 1;
int size = slime.getSize();
while (size > 1) {
size /= 2;
int currentSlimes = totalSlimes;
totalSlimes = StackerUtils.randomInRange(currentSlimes * 2, currentSlimes * 4);
}
iterations = totalSlimes;
}
slime.setSize(1);
}
boolean isBaby = isAnimal && !((Animals) entity).isAdult();
int desiredExp = isBaby ? 0 : droppedExp;
for (int i = 0; i < iterations; i++) {
Collection<ItemStack> entityLoot = isBaby ? Collections.emptyList() : EntityUtils.getEntityLoot(entity, thisEntity.getKiller(), thisEntity.getLocation());
if (callEvents && !multiplyCustomLoot) {
EntityDeathEvent deathEvent = new AsyncEntityDeathEvent(entity, new ArrayList<>(entityLoot), desiredExp);
Bukkit.getPluginManager().callEvent(deathEvent);
totalExp += deathEvent.getDroppedExp();
loot.addAll(deathEvent.getDrops());
} else {
loot.addAll(entityLoot);
totalExp += desiredExp;
}
}
}
if (multiplyCustomLoot) {
EntityDeathEvent deathEvent = new EntityDeathEvent(thisEntity, new ArrayList<>(), 0);
for (int i = 0, k = this.getStackSize() - 1; i < k; i++) loot.addAll(deathEvent.getDrops());
totalExp += deathEvent.getDroppedExp() * (this.getStackSize() - 1);
}
int finalTotalExp = totalExp;
Runnable finishTask = () -> {
RoseStacker.getInstance().getManager(StackManager.class).preStackItems(loot, thisEntity.getLocation());
if (Setting.ENTITY_DROP_ACCURATE_EXP.getBoolean() && finalTotalExp > 0)
StackerUtils.dropExperience(thisEntity.getLocation(), finalTotalExp, finalTotalExp, finalTotalExp / 2);
};
// Withers always drop nether stars on death, however this isn't in the actual wither loot table for some reason
if (this.entity.getType() == EntityType.WITHER)
loot.addAll(GuiUtil.getMaterialAmountAsItemStacks(Material.NETHER_STAR, internalEntities.size()));
if (async) {
Bukkit.getScheduler().runTask(RoseStacker.getInstance(), finishTask);
} else {
finishTask.run();
}
};
if (async) {
Bukkit.getScheduler().runTaskAsynchronously(RoseStacker.getInstance(), mainTask);
} else {
mainTask.run();
}
}
use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class StackedEntity method updateDisplay.
@Override
public void updateDisplay() {
this.displayName = null;
String displayName = this.getDisplayName();
NMSHandler nmsHandler = NMSAdapter.getHandler();
for (Player player : this.getPlayersInVisibleRange()) nmsHandler.updateEntityNameTagForPlayer(player, this.entity, displayName, this.displayNameVisible);
}
use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class StackedEntity method dropStackLoot.
/**
* Drops all loot and experience for all internally-stacked entities.
* Does not include loot for the current entity.
*
* @param existingLoot The loot from this.entity, nullable
* @param droppedExp The exp dropped from this.entity
*/
public void dropStackLoot(Collection<ItemStack> existingLoot, int droppedExp) {
// Cache the current entity just in case it somehow changes while we are processing the loot
LivingEntity thisEntity = this.entity;
Bukkit.getScheduler().runTaskAsynchronously(RoseStacker.getInstance(), () -> {
List<LivingEntity> internalEntities = new ArrayList<>();
NMSHandler nmsHandler = NMSAdapter.getHandler();
for (StackedEntityDataEntry<?> entityNBT : this.serializedStackedEntities.getAll()) {
LivingEntity entity = nmsHandler.createEntityFromNBT(entityNBT, thisEntity.getLocation(), false, thisEntity.getType());
if (entity == null)
continue;
internalEntities.add(entity);
}
Bukkit.getScheduler().runTask(RoseStacker.getInstance(), () -> this.dropPartialStackLoot(internalEntities, existingLoot, droppedExp));
});
}
use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class MobSpawningMethod method spawnEntitiesIntoNearbyStacks.
private int spawnEntitiesIntoNearbyStacks(StackedSpawner stackedSpawner, int spawnAmount, Set<Location> locations, List<StackedEntity> nearbyEntities, StackManager stackManager) {
EntityStackSettings entityStackSettings = RoseStacker.getInstance().getManager(StackSettingManager.class).getEntityStackSettings(this.entityType);
List<StackedEntity> stackedEntities = new ArrayList<>(nearbyEntities);
List<Location> possibleLocations = new ArrayList<>(locations);
if (this.entityType.getEntityClass() == null)
return 0;
boolean ageable = Ageable.class.isAssignableFrom(this.entityType.getEntityClass());
int successfulSpawns = 0;
if (stackManager.isEntityStackingEnabled() && entityStackSettings.isStackingEnabled() && Setting.SPAWNER_SPAWN_INTO_NEARBY_STACKS.getBoolean()) {
List<StackedEntity> newStacks = new ArrayList<>();
NMSHandler nmsHandler = NMSAdapter.getHandler();
for (int i = 0; i < spawnAmount; i++) {
if (possibleLocations.isEmpty())
break;
Location location = possibleLocations.get(this.random.nextInt(possibleLocations.size()));
LivingEntity entity = nmsHandler.createNewEntityUnspawned(this.entityType, location, CreatureSpawnEvent.SpawnReason.SPAWNER);
SpawnerFlagPersistenceHook.flagSpawnerSpawned(entity);
if (ageable)
((Ageable) entity).setAdult();
if ((stackedSpawner.getStackSettings().isMobAIDisabled() && (!Setting.SPAWNER_DISABLE_MOB_AI_ONLY_PLAYER_PLACED.getBoolean() || stackedSpawner.isPlacedByPlayer())) || Setting.ENTITY_DISABLE_ALL_MOB_AI.getBoolean())
PersistentDataUtils.removeEntityAi(entity);
PersistentDataUtils.tagSpawnedFromSpawner(entity);
entityStackSettings.applySpawnerSpawnedProperties(entity);
StackedEntity newStack = new StackedEntity(entity);
Optional<StackedEntity> matchingEntity = stackedEntities.stream().filter(x -> WorldGuardHook.testLocation(x.getLocation()) && entityStackSettings.testCanStackWith(x, newStack, false, true)).findFirst();
if (matchingEntity.isPresent()) {
matchingEntity.get().increaseStackSize(entity);
} else {
stackedEntities.add(newStack);
newStacks.add(newStack);
possibleLocations.remove(location);
}
successfulSpawns++;
}
Bukkit.getScheduler().runTask(RoseStacker.getInstance(), () -> {
stackManager.setEntityStackingTemporarilyDisabled(true);
for (StackedEntity stackedEntity : newStacks) {
LivingEntity entity = stackedEntity.getEntity();
SpawnerSpawnEvent spawnerSpawnEvent = new SpawnerSpawnEvent(entity, stackedSpawner.getSpawner());
Bukkit.getPluginManager().callEvent(spawnerSpawnEvent);
if (spawnerSpawnEvent.isCancelled())
continue;
nmsHandler.spawnExistingEntity(stackedEntity.getEntity(), CreatureSpawnEvent.SpawnReason.SPAWNER, Setting.SPAWNER_BYPASS_REGION_SPAWNING_RULES.getBoolean());
entity.setVelocity(Vector.getRandom().multiply(0.01));
stackManager.addEntityStack(stackedEntity);
}
stackManager.setEntityStackingTemporarilyDisabled(false);
// Spawn particles for new entities and update nametags
for (StackedEntity entity : newStacks) {
entity.updateDisplay();
World world = entity.getLocation().getWorld();
if (world != null)
world.spawnParticle(Particle.EXPLOSION_NORMAL, entity.getLocation().clone().add(0, 0.75, 0), 5, 0.25, 0.25, 0.25, 0.01);
}
});
} else {
successfulSpawns = Math.min(spawnAmount, possibleLocations.size());
Bukkit.getScheduler().runTask(RoseStacker.getInstance(), () -> {
NMSHandler nmsHandler = NMSAdapter.getHandler();
for (int i = 0; i < spawnAmount; i++) {
if (possibleLocations.isEmpty())
break;
Location location = possibleLocations.remove(this.random.nextInt(possibleLocations.size()));
World world = location.getWorld();
if (world == null)
continue;
LivingEntity entity = nmsHandler.spawnEntityWithReason(this.entityType, location, CreatureSpawnEvent.SpawnReason.SPAWNER, Setting.SPAWNER_BYPASS_REGION_SPAWNING_RULES.getBoolean());
entityStackSettings.applySpawnerSpawnedProperties(entity);
SpawnerFlagPersistenceHook.flagSpawnerSpawned(entity);
SpawnerSpawnEvent spawnerSpawnEvent = new SpawnerSpawnEvent(entity, stackedSpawner.getSpawner());
Bukkit.getPluginManager().callEvent(spawnerSpawnEvent);
if (spawnerSpawnEvent.isCancelled()) {
entity.remove();
continue;
}
// Spawn Particles
if (entity.isValid())
entity.getWorld().spawnParticle(Particle.EXPLOSION_NORMAL, entity.getLocation().clone().add(0, 0.75, 0), 5, 0.25, 0.25, 0.25, 0.01);
}
});
}
return successfulSpawns;
}
Aggregations