use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class EntityStackSettings method canStackWith.
/**
* Checks if one StackedEntity can stack with another and returns the comparison result
*
* @param stack1 The first stack
* @param stack2 The second stack
* @param comparingForUnstack true if the comparison is being made for unstacking, false otherwise
* @param ignorePositions true if position checks for the entities should be ignored, false otherwise
* @return the comparison result
*/
public EntityStackComparisonResult canStackWith(StackedEntity stack1, StackedEntity stack2, boolean comparingForUnstack, boolean ignorePositions) {
LivingEntity entity1 = stack1.getEntity();
LivingEntity entity2 = stack2.getEntity();
if (entity1.getType() != entity2.getType())
return EntityStackComparisonResult.DIFFERENT_ENTITY_TYPES;
if (!this.enabled)
return EntityStackComparisonResult.STACKING_NOT_ENABLED;
int offset = comparingForUnstack ? -1 : 0;
if (stack1.getStackSize() + stack2.getStackSize() + offset > this.getMaxStackSize())
return EntityStackComparisonResult.STACK_SIZE_TOO_LARGE;
if (PersistentDataUtils.isUnstackable(entity1) || PersistentDataUtils.isUnstackable(entity2))
return EntityStackComparisonResult.MARKED_UNSTACKABLE;
if (Setting.ENTITY_DONT_STACK_CUSTOM_NAMED.getBoolean() && (entity1.getCustomName() != null || entity2.getCustomName() != null))
return EntityStackComparisonResult.CUSTOM_NAMED;
if (!comparingForUnstack && !ignorePositions && !this.getEntityTypeData().isSwimmingMob() && !this.getEntityTypeData().isFlyingMob()) {
if (Setting.ENTITY_ONLY_STACK_ON_GROUND.getBoolean() && (!entity1.isOnGround() || !entity2.isOnGround()))
return EntityStackComparisonResult.NOT_ON_GROUND;
if (Setting.ENTITY_DONT_STACK_IF_IN_WATER.getBoolean() && (entity1.getLocation().getBlock().getType() == Material.WATER || entity2.getLocation().getBlock().getType() == Material.WATER))
return EntityStackComparisonResult.IN_WATER;
}
if (!comparingForUnstack && this.shouldOnlyStackFromSpawners() && (!PersistentDataUtils.isSpawnedFromSpawner(entity1) || !PersistentDataUtils.isSpawnedFromSpawner(entity2)))
return EntityStackComparisonResult.NOT_SPAWNED_FROM_SPAWNER;
// Don't stack if being ridden or is riding something
if ((!entity1.getPassengers().isEmpty() || !entity2.getPassengers().isEmpty() || entity1.isInsideVehicle() || entity2.isInsideVehicle()) && !comparingForUnstack)
// If comparing for unstack and is being ridden or is riding something, don't want to unstack it
return EntityStackComparisonResult.PART_OF_VEHICLE;
if (!comparingForUnstack && Setting.ENTITY_DONT_STACK_IF_LEASHED.getBoolean() && (entity1.isLeashed() || entity2.isLeashed()))
return EntityStackComparisonResult.LEASHED;
if (Setting.ENTITY_DONT_STACK_IF_INVULNERABLE.getBoolean() && (entity1.isInvulnerable() || entity2.isInvulnerable()))
return EntityStackComparisonResult.INVULNERABLE;
if (Setting.ENTITY_DONT_STACK_IF_HAS_EQUIPMENT.getBoolean()) {
EntityEquipment equipment1 = entity1.getEquipment();
EntityEquipment equipment2 = entity2.getEquipment();
if (equipment1 != null)
for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) if (equipment1.getItem(equipmentSlot).getType() != Material.AIR)
return EntityStackComparisonResult.HAS_EQUIPMENT;
if (equipment2 != null)
for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) if (equipment2.getItem(equipmentSlot).getType() != Material.AIR)
return EntityStackComparisonResult.HAS_EQUIPMENT;
}
if (this.isEntityColorable()) {
Colorable colorable1 = (Colorable) entity1;
Colorable colorable2 = (Colorable) entity2;
if (this.dontStackIfDifferentColor && colorable1.getColor() != colorable2.getColor())
return EntityStackComparisonResult.DIFFERENT_COLORS;
}
if (this.isEntitySittable()) {
Sittable sittable1 = (Sittable) entity1;
Sittable sittable2 = (Sittable) entity2;
if (this.dontStackIfSitting && (sittable1.isSitting() || sittable2.isSitting()))
return EntityStackComparisonResult.SITTING;
}
if (this.isEntityTameable()) {
Tameable tameable1 = (Tameable) entity1;
Tameable tameable2 = (Tameable) entity2;
if (this.dontStackIfTamed && (tameable1.isTamed() || tameable2.isTamed()))
return EntityStackComparisonResult.TAMED;
if (this.dontStackIfDifferentOwners) {
AnimalTamer tamer1 = tameable1.getOwner();
AnimalTamer tamer2 = tameable2.getOwner();
if (tamer1 != null && tamer2 != null && !tamer1.getUniqueId().equals(tamer2.getUniqueId()))
return EntityStackComparisonResult.DIFFERENT_OWNERS;
}
}
if (this.isEntityAnimals()) {
Animals animals1 = (Animals) entity1;
Animals animals2 = (Animals) entity2;
NMSHandler nmsHandler = NMSAdapter.getHandler();
boolean hasEgg = animals1.getType() == EntityType.TURTLE && (nmsHandler.isTurtlePregnant((Turtle) animals1) || nmsHandler.isTurtlePregnant((Turtle) animals2));
if (this.dontStackIfBreeding && (animals1.isLoveMode() || animals2.isLoveMode() || (!animals1.canBreed() && animals1.isAdult()) || (!animals2.canBreed() && animals2.isAdult()) || hasEgg))
return EntityStackComparisonResult.BREEDING;
}
if (this.isEntityAgeable()) {
Ageable ageable1 = (Ageable) entity1;
Ageable ageable2 = (Ageable) entity2;
if (this.dontStackIfDifferentAge && ageable1.isAdult() != ageable2.isAdult())
return EntityStackComparisonResult.DIFFERENT_AGES;
if (this.dontStackIfBaby && (!ageable1.isAdult() || !ageable2.isAdult()))
return EntityStackComparisonResult.BABY;
}
if (this.isEntityAbstractHorse()) {
AbstractHorse abstractHorse1 = (AbstractHorse) entity1;
AbstractHorse abstractHorse2 = (AbstractHorse) entity2;
if (this.dontStackIfSaddled && (abstractHorse1.getInventory().getSaddle() != null || abstractHorse2.getInventory().getSaddle() != null))
return EntityStackComparisonResult.SADDLED;
}
if (this.isEntityChestedHorse()) {
ChestedHorse chestedHorse1 = (ChestedHorse) entity1;
ChestedHorse chestedHorse2 = (ChestedHorse) entity2;
if (this.dontStackIfChested && (chestedHorse1.isCarryingChest() || chestedHorse2.isCarryingChest()))
return EntityStackComparisonResult.HAS_CHEST;
}
if (this.isEntityRaider()) {
Raider raider1 = (Raider) entity1;
Raider raider2 = (Raider) entity2;
if (this.dontStackIfPatrolLeader && (raider1.isPatrolLeader() || raider2.isPatrolLeader()))
return EntityStackComparisonResult.PATROL_LEADER;
if (Setting.ENTITY_DONT_STACK_IF_ACTIVE_RAIDER.getBoolean() && (RaidListener.isActiveRaider(raider1) || RaidListener.isActiveRaider(raider2)))
return EntityStackComparisonResult.PART_OF_ACTIVE_RAID;
}
if (this.isEntityMerchant()) {
Merchant merchant1 = (Merchant) entity1;
Merchant merchant2 = (Merchant) entity2;
if (this.dontStackIfTrading && (merchant1.isTrading() || merchant2.isTrading()))
return EntityStackComparisonResult.TRADING;
}
return this.canStackWithInternal(stack1, stack2);
}
use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class StackingThread method preStackEntities.
@Override
public void preStackEntities(EntityType entityType, int amount, Location location, SpawnReason spawnReason) {
World world = location.getWorld();
if (world == null)
return;
Bukkit.getScheduler().runTaskAsynchronously(this.rosePlugin, () -> {
EntityStackSettings stackSettings = this.rosePlugin.getManager(StackSettingManager.class).getEntityStackSettings(entityType);
Set<StackedEntity> stackedEntities = new HashSet<>();
NMSHandler nmsHandler = NMSAdapter.getHandler();
for (int i = 0; i < amount; i++) {
LivingEntity entity = nmsHandler.createNewEntityUnspawned(entityType, location, spawnReason);
StackedEntity newStack = new StackedEntity(entity);
Optional<StackedEntity> matchingEntity = stackedEntities.stream().filter(x -> stackSettings.testCanStackWith(x, newStack, false, true)).findFirst();
if (matchingEntity.isPresent()) {
matchingEntity.get().increaseStackSize(entity, false);
} else {
stackedEntities.add(newStack);
}
}
Bukkit.getScheduler().runTask(this.rosePlugin, () -> {
this.stackManager.setEntityStackingTemporarilyDisabled(true);
for (StackedEntity stackedEntity : stackedEntities) {
LivingEntity entity = stackedEntity.getEntity();
this.entityCacheManager.preCacheEntity(entity);
nmsHandler.spawnExistingEntity(stackedEntity.getEntity(), spawnReason, Setting.SPAWNER_BYPASS_REGION_SPAWNING_RULES.getBoolean());
entity.setVelocity(Vector.getRandom().multiply(0.01));
this.addEntityStack(stackedEntity);
stackedEntity.updateDisplay();
}
this.stackManager.setEntityStackingTemporarilyDisabled(false);
});
});
}
use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class StackingThread method processNametags.
public void processNametags() {
if (!this.dynamicEntityTags && !this.dynamicItemTags && !this.dynamicBlockTags)
return;
List<Player> players = this.targetWorld.getPlayers();
if (players.isEmpty())
return;
// Handle dynamic stack tags
NMSHandler nmsHandler = NMSAdapter.getHandler();
Set<EntityType> validEntities = StackerUtils.getStackableEntityTypes();
boolean displaySingleEntityTags = Setting.ENTITY_DISPLAY_TAGS_SINGLE.getBoolean();
boolean displaySingleItemTags = Setting.ITEM_DISPLAY_TAGS_SINGLE.getBoolean();
List<Entity> entities = new ArrayList<>();
entities.addAll(this.stackedEntities.values().stream().filter(x -> x.getStackSize() > 1 || displaySingleEntityTags).map(StackedEntity::getEntity).filter(Objects::nonNull).filter(x -> validEntities.contains(x.getType())).collect(Collectors.toList()));
entities.addAll(this.stackedItems.values().stream().filter(x -> x.getStackSize() > 1 || displaySingleItemTags).map(StackedItem::getItem).collect(Collectors.toList()));
for (Player player : players) {
if (player.getWorld() != this.targetWorld)
continue;
ItemStack itemStack = player.getInventory().getItemInMainHand();
boolean displayStackingToolParticles = ItemUtils.isStackingTool(itemStack);
for (Entity entity : entities) {
if (entity.getType() == EntityType.PLAYER)
continue;
if ((entity.getType() == EntityType.DROPPED_ITEM || entity.getType() == EntityType.ARMOR_STAND) && (entity.getCustomName() == null || !entity.isCustomNameVisible()))
continue;
double distanceSqrd;
try {
// The locations can end up comparing cross-world if the player/entity switches worlds mid-loop due to being async
distanceSqrd = player.getLocation().distanceSquared(entity.getLocation());
} catch (Exception e) {
continue;
}
if (distanceSqrd > StackerUtils.ASSUMED_ENTITY_VISIBILITY_RANGE)
continue;
boolean visible;
if (this.dynamicItemTags && entity.getType() == EntityType.DROPPED_ITEM) {
visible = distanceSqrd < this.itemDynamicViewRangeSqrd;
if (this.itemDynamicWallDetection)
visible &= EntityUtils.hasLineOfSight(player, entity, 0.75, true);
} else if (this.dynamicBlockTags && entity.getType() == EntityType.ARMOR_STAND) {
visible = distanceSqrd < this.blockSpawnerDynamicViewRangeSqrd;
if (this.blockDynamicWallDetection)
visible &= EntityUtils.hasLineOfSight(player, entity, 0.75, true);
} else if (this.dynamicEntityTags) {
visible = distanceSqrd < this.entityDynamicViewRangeSqrd;
if (this.entityDynamicWallDetection)
visible &= EntityUtils.hasLineOfSight(player, entity, 0.75, true);
} else
continue;
if (entity.getType() != EntityType.ARMOR_STAND && entity instanceof LivingEntity) {
LivingEntity livingEntity = (LivingEntity) entity;
StackedEntity stackedEntity = this.getStackedEntity(livingEntity);
if (stackedEntity != null)
nmsHandler.updateEntityNameTagForPlayer(player, entity, stackedEntity.getDisplayName(), stackedEntity.isDisplayNameVisible() && visible);
// Spawn particles for holding the stacking tool
if (visible && displayStackingToolParticles) {
Location location = entity.getLocation().add(0, livingEntity.getEyeHeight(true) + 0.75, 0);
DustOptions dustOptions;
if (PersistentDataUtils.isUnstackable(livingEntity)) {
dustOptions = StackerUtils.UNSTACKABLE_DUST_OPTIONS;
} else {
dustOptions = StackerUtils.STACKABLE_DUST_OPTIONS;
}
player.spawnParticle(Particle.REDSTONE, location, 1, 0.0, 0.0, 0.0, 0.0, dustOptions);
}
} else {
nmsHandler.updateEntityNameTagVisibilityForPlayer(player, entity, visible);
}
}
}
}
use of dev.rosewood.rosestacker.nms.NMSHandler in project RoseStacker by Rosewood-Development.
the class StackedEntity method shouldStayStacked.
/**
* @return true if this entity should stay stacked, otherwise false
*/
public boolean shouldStayStacked() {
if (this.entity == null || this.serializedStackedEntities.isEmpty())
return true;
// We want to be able to do this check async, we just won't let ender dragons unstack without dying
if (this.entity instanceof EnderDragon)
return true;
NMSHandler nmsHandler = NMSAdapter.getHandler();
LivingEntity entity = nmsHandler.createEntityFromNBT(this.serializedStackedEntities.peek(), this.entity.getLocation(), false, this.entity.getType());
StackedEntity stackedEntity = new StackedEntity(entity, nmsHandler.createEntityDataStorage(entity));
return this.stackSettings.testCanStackWith(this, stackedEntity, true);
}
Aggregations