diff --git a/pom.xml b/pom.xml
index 7dc310673..a9c9ab3c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
me.lokka30
LevelledMobs
- 3.2.4 b557
+ 3.2.5 b564
jar
LevelledMobs
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java
index 00522ec3c..a78cb1f39 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java
@@ -68,6 +68,9 @@ public void onEntitySpawn(@NotNull final EntitySpawnEvent event) {
return;
}
+ if (event instanceof CreatureSpawnEvent && ((CreatureSpawnEvent) event).getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.SPAWNER))
+ lmEntity.setSpawnReason(LevelledMobSpawnReason.SPAWNER);
+
if (main.configUtils.playerLevellingEnabled && lmEntity.getPlayerForLevelling() == null)
updateMobForPlayerLevelling(lmEntity);
@@ -206,6 +209,7 @@ public void run() {
public void preprocessMob(final @NotNull LivingEntityWrapper lmEntity, @NotNull final Event event){
if (!lmEntity.reEvaluateLevel && lmEntity.isLevelled())
return;
+ if (lmEntity.getLivingEntity() == null) return;
LevelledMobSpawnReason spawnReason = LevelledMobSpawnReason.DEFAULT;
AdditionalLevelInformation additionalInfo = AdditionalLevelInformation.NOT_APPLICABLE;
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java b/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java
index b1b283250..2794f25a9 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java
@@ -1198,9 +1198,34 @@ private void getPlayersNearMob(final @NotNull LivingEntityWrapper lmEntity){
* @return if the mob is levelled or not
*/
public boolean isLevelled(@NotNull final LivingEntity livingEntity) {
- synchronized (livingEntity.getPersistentDataContainer()) {
- return livingEntity.getPersistentDataContainer().has(main.namespaced_keys.levelKey, PersistentDataType.INTEGER);
+ boolean hadError = false;
+ boolean succeeded = false;
+ boolean isLevelled = false;
+
+ for (int i = 0; i < 2; i++) {
+ try {
+ synchronized (livingEntity.getPersistentDataContainer()) {
+ isLevelled = livingEntity.getPersistentDataContainer().has(main.namespaced_keys.levelKey, PersistentDataType.INTEGER);
+ }
+ succeeded = true;
+ break;
+ }
+ catch (ConcurrentModificationException ignored) {
+ hadError = true;
+ try
+ { Thread.sleep(10); }
+ catch (InterruptedException ignored2) { return false; }
+ }
}
+
+ if (hadError) {
+ if (succeeded)
+ Utils.logger.warning("Got ConcurrentModificationException in LevelManager checking entity isLevelled, succeeded on retry");
+ else
+ Utils.logger.warning("Got ConcurrentModificationException (2x) in LevelManager checking entity isLevelled");
+ }
+
+ return isLevelled;
}
/**
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java b/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java
index c105a9c02..0e9a09478 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java
@@ -67,13 +67,22 @@ private void main() throws InterruptedException{
final QueueItem item = queue.poll(200, TimeUnit.MILLISECONDS);
if (item == null) continue;
- if (item.lmEntity.getLivingEntity() != null) {
- if (!item.lmEntity.getIsPopulated()) continue;
- if (!item.lmEntity.getShouldShowLM_Nametag()) continue;
- main.levelManager.entitySpawnListener.preprocessMob(item.lmEntity, item.event);
+ String lastEntityType = null;
+ try {
+ if (item.lmEntity.getLivingEntity() != null) {
+ if (!item.lmEntity.getIsPopulated()) continue;
+ if (!item.lmEntity.getShouldShowLM_Nametag()) continue;
+ lastEntityType = item.lmEntity.getNameIfBaby();
+ main.levelManager.entitySpawnListener.preprocessMob(item.lmEntity, item.event);
+ }
+ }
+ catch (Exception e){
+ Utils.logger.error("Got exception while processing " + (lastEntityType != null ? lastEntityType : "(unknown)"));
+ e.printStackTrace();
+ }
+ finally {
+ item.lmEntity.free();
}
-
- item.lmEntity.free();
}
isRunning = false;
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java b/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java
index 0d9cf4146..08c2ccfe8 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java
@@ -88,60 +88,74 @@ private void main() throws InterruptedException{
continue;
}
- final int nametagTimerResetTime = item.lmEntity.getNametagCooldownTime();
+ String lastEntityType = null;
+ try {
+ lastEntityType = item.lmEntity.getNameIfBaby();
+ processItem(item);
+ }
+ catch (Exception e){
+ Utils.logger.error("Got exception while processing nametag updates on " + (lastEntityType != null ? lastEntityType : "(unknown)"));
+ e.printStackTrace();
+ }
+ finally {
+ item.lmEntity.free();
+ }
+ }
- if (nametagTimerResetTime > 0 && !"".equals(item.nametag)) {
- synchronized (NametagTimerChecker.nametagTimer_Lock) {
- final Map> nametagCooldownQueue = main.nametagTimerChecker.getNametagCooldownQueue();
+ isRunning = false;
+ }
- if (item.lmEntity.playersNeedingNametagCooldownUpdate != null) {
- // record which players should get the cooldown for this mob
- // public Map> nametagCooldownQueue;
- for (final Player player : item.lmEntity.playersNeedingNametagCooldownUpdate) {
- if (!nametagCooldownQueue.containsKey(player)) continue;
+ private void processItem(final @NotNull QueueItem item){
+ final int nametagTimerResetTime = item.lmEntity.getNametagCooldownTime();
- nametagCooldownQueue.get(player).put(item.lmEntity.getLivingEntity(), Instant.now());
- main.nametagTimerChecker.cooldownTimes.put(item.lmEntity.getLivingEntity(), item.lmEntity.getNametagCooldownTime());
- }
+ if (nametagTimerResetTime > 0 && !"".equals(item.nametag)) {
+ synchronized (NametagTimerChecker.nametagTimer_Lock) {
+ final Map> nametagCooldownQueue = main.nametagTimerChecker.getNametagCooldownQueue();
- // if any players already have a cooldown on this mob then don't remove the cooldown
- for (final Player player : nametagCooldownQueue.keySet()){
- if (item.lmEntity.playersNeedingNametagCooldownUpdate.contains(player)) continue;
+ if (item.lmEntity.playersNeedingNametagCooldownUpdate != null) {
+ // record which players should get the cooldown for this mob
+ // public Map> nametagCooldownQueue;
+ for (final Player player : item.lmEntity.playersNeedingNametagCooldownUpdate) {
+ if (!nametagCooldownQueue.containsKey(player)) continue;
- if (nametagCooldownQueue.get(player).containsKey(item.lmEntity.getLivingEntity()))
- item.lmEntity.playersNeedingNametagCooldownUpdate.add(player);
- }
+ nametagCooldownQueue.get(player).put(item.lmEntity.getLivingEntity(), Instant.now());
+ main.nametagTimerChecker.cooldownTimes.put(item.lmEntity.getLivingEntity(), item.lmEntity.getNametagCooldownTime());
}
- else{
- // if there's any existing cooldowns we'll use them
- for (final Player player : nametagCooldownQueue.keySet()){
- if (nametagCooldownQueue.get(player).containsKey(item.lmEntity.getLivingEntity())) {
- if (item.lmEntity.playersNeedingNametagCooldownUpdate == null)
- item.lmEntity.playersNeedingNametagCooldownUpdate = new HashSet<>();
-
- item.lmEntity.playersNeedingNametagCooldownUpdate.add(player);
- }
+
+ // if any players already have a cooldown on this mob then don't remove the cooldown
+ for (final Player player : nametagCooldownQueue.keySet()){
+ if (item.lmEntity.playersNeedingNametagCooldownUpdate.contains(player)) continue;
+
+ if (nametagCooldownQueue.get(player).containsKey(item.lmEntity.getLivingEntity()))
+ item.lmEntity.playersNeedingNametagCooldownUpdate.add(player);
+ }
+ }
+ else{
+ // if there's any existing cooldowns we'll use them
+ for (final Player player : nametagCooldownQueue.keySet()){
+ if (nametagCooldownQueue.get(player).containsKey(item.lmEntity.getLivingEntity())) {
+ if (item.lmEntity.playersNeedingNametagCooldownUpdate == null)
+ item.lmEntity.playersNeedingNametagCooldownUpdate = new HashSet<>();
+
+ item.lmEntity.playersNeedingNametagCooldownUpdate.add(player);
}
}
}
}
- else if (item.lmEntity.playersNeedingNametagCooldownUpdate != null)
- item.lmEntity.playersNeedingNametagCooldownUpdate = null;
+ }
+ else if (item.lmEntity.playersNeedingNametagCooldownUpdate != null)
+ item.lmEntity.playersNeedingNametagCooldownUpdate = null;
- synchronized (NametagTimerChecker.entityTarget_Lock){
- if (main.nametagTimerChecker.entityTargetMap.containsKey(item.lmEntity.getLivingEntity())){
- if (item.lmEntity.playersNeedingNametagCooldownUpdate == null)
- item.lmEntity.playersNeedingNametagCooldownUpdate = new HashSet<>();
+ synchronized (NametagTimerChecker.entityTarget_Lock){
+ if (main.nametagTimerChecker.entityTargetMap.containsKey(item.lmEntity.getLivingEntity())){
+ if (item.lmEntity.playersNeedingNametagCooldownUpdate == null)
+ item.lmEntity.playersNeedingNametagCooldownUpdate = new HashSet<>();
- item.lmEntity.playersNeedingNametagCooldownUpdate.add(main.nametagTimerChecker.entityTargetMap.get(item.lmEntity.getLivingEntity()));
- }
+ item.lmEntity.playersNeedingNametagCooldownUpdate.add(main.nametagTimerChecker.entityTargetMap.get(item.lmEntity.getLivingEntity()));
}
-
- updateNametag(item.lmEntity, item.nametag, item.players);
- item.lmEntity.free();
}
- isRunning = false;
+ updateNametag(item.lmEntity, item.nametag, item.players);
}
private void updateNametag(final @NotNull LivingEntityWrapper lmEntity, final String nametag, final List players) {