From 9029884f3de64ccbf651b1b0a0180a34b94a04a2 Mon Sep 17 00:00:00 2001
From: Zoey76 <zoey_76@msn.com>
Date: Sat, 11 Jul 2015 23:10:20 -0300
Subject: [PATCH] Fixing Elpies not being despawned on custom event

- Fixed concurrency issues and legacy code.

Reported by: @Avanael
---
 .../scripts/custom/events/Elpies/Elpies.java  | 24 ++++++-------
 .../custom/events/Rabbits/Rabbits.java        | 16 ++++-----
 .../data/scripts/custom/events/Race/Race.java | 34 +++++++------------
 3 files changed, 30 insertions(+), 44 deletions(-)

diff --git a/L2J_DataPack/dist/game/data/scripts/custom/events/Elpies/Elpies.java b/L2J_DataPack/dist/game/data/scripts/custom/events/Elpies/Elpies.java
index b8d9b25d84..8f9fe6935d 100644
--- a/L2J_DataPack/dist/game/data/scripts/custom/events/Elpies/Elpies.java
+++ b/L2J_DataPack/dist/game/data/scripts/custom/events/Elpies/Elpies.java
@@ -18,12 +18,12 @@
  */
 package custom.events.Elpies;
 
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledFuture;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.datatables.SpawnTable;
-import com.l2jserver.gameserver.model.L2Spawn;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2EventMonsterInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
@@ -64,8 +64,8 @@ public final class Elpies extends Event
 	// @formatter:on
 	// Non-final variables
 	private static boolean EVENT_ACTIVE = false;
-	private static int CURRENT_ELPY_COUNT = 0;
 	private ScheduledFuture<?> _eventTask = null;
+	private final Set<L2Npc> _elpies = ConcurrentHashMap.newKeySet(ELPY_AMOUNT);
 	
 	private Elpies()
 	{
@@ -101,13 +101,11 @@ public final class Elpies extends Event
 		EventLocation[] locations = EventLocation.values();
 		EventLocation randomLoc = locations[getRandom(locations.length)];
 		
-		CURRENT_ELPY_COUNT = 0;
 		long despawnDelay = EVENT_DURATION_MINUTES * 60000;
 		
 		for (int i = 0; i < ELPY_AMOUNT; i++)
 		{
-			addSpawn(ELPY, randomLoc.getRandomX(), randomLoc.getRandomY(), randomLoc.getZ(), 0, true, despawnDelay);
-			CURRENT_ELPY_COUNT++;
+			_elpies.add(addSpawn(ELPY, randomLoc.getRandomX(), randomLoc.getRandomY(), randomLoc.getZ(), 0, true, despawnDelay));
 		}
 		
 		Broadcast.toAllOnlinePlayers("*Squeak Squeak*");
@@ -139,14 +137,11 @@ public final class Elpies extends Event
 			_eventTask = null;
 		}
 		
-		for (L2Spawn spawn : SpawnTable.getInstance().getSpawns(ELPY))
+		for (L2Npc npc : _elpies)
 		{
-			L2Npc npc = spawn.getLastSpawn();
-			if (npc != null)
-			{
-				npc.deleteMe();
-			}
+			npc.deleteMe();
 		}
+		_elpies.clear();
 		
 		Broadcast.toAllOnlinePlayers("*Squeak Squeak*");
 		Broadcast.toAllOnlinePlayers("Elpy Event finished!");
@@ -158,11 +153,12 @@ public final class Elpies extends Event
 	{
 		if (EVENT_ACTIVE)
 		{
+			_elpies.remove(npc);
+			
 			dropItem(npc, killer, DROPLIST_CONSUMABLES);
 			dropItem(npc, killer, DROPLIST_CRYSTALS);
-			CURRENT_ELPY_COUNT--;
 			
-			if (CURRENT_ELPY_COUNT <= 0)
+			if (_elpies.isEmpty())
 			{
 				Broadcast.toAllOnlinePlayers("All elpies have been killed!");
 				eventStop();
diff --git a/L2J_DataPack/dist/game/data/scripts/custom/events/Rabbits/Rabbits.java b/L2J_DataPack/dist/game/data/scripts/custom/events/Rabbits/Rabbits.java
index 2ca12435e9..8232152b31 100644
--- a/L2J_DataPack/dist/game/data/scripts/custom/events/Rabbits/Rabbits.java
+++ b/L2J_DataPack/dist/game/data/scripts/custom/events/Rabbits/Rabbits.java
@@ -20,7 +20,8 @@ package custom.events.Rabbits;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.model.L2Object;
@@ -51,7 +52,7 @@ public final class Rabbits extends Event
 	private static final int EVENT_TIME = 10;
 	private static final int TOTAL_CHEST_COUNT = 75;
 	private static final int TRANSFORMATION_ID = 105;
-	private final List<L2Npc> _npcs = new CopyOnWriteArrayList<>();
+	private final Set<L2Npc> _npcs = ConcurrentHashMap.newKeySet(TOTAL_CHEST_COUNT + 1);
 	private final List<L2PcInstance> _players = new ArrayList<>();
 	private boolean _isActive = false;
 	
@@ -142,16 +143,13 @@ public final class Rabbits extends Event
 		// Despawn NPCs
 		for (L2Npc npc : _npcs)
 		{
-			if (npc != null)
-			{
-				npc.deleteMe();
-			}
+			npc.deleteMe();
 		}
 		_npcs.clear();
 		
 		for (L2PcInstance player : _players)
 		{
-			if ((player != null) && (player.getTransformationId() == TRANSFORMATION_ID))
+			if (player.getTransformationId() == TRANSFORMATION_ID)
 			{
 				player.untransform();
 			}
@@ -213,7 +211,7 @@ public final class Rabbits extends Event
 				npc.deleteMe();
 				_npcs.remove(npc);
 				
-				if (_npcs.size() <= 1)
+				if (_npcs.isEmpty())
 				{
 					Broadcast.toAllOnlinePlayers("Rabbits Event: No more chests...");
 					eventStop();
@@ -253,7 +251,7 @@ public final class Rabbits extends Event
 		}
 	}
 	
-	private static void recordSpawn(List<L2Npc> npcs, int npcId, int x, int y, int z, int heading, boolean randomOffSet, long despawnDelay)
+	private static void recordSpawn(Set<L2Npc> npcs, int npcId, int x, int y, int z, int heading, boolean randomOffSet, long despawnDelay)
 	{
 		final L2Npc npc = addSpawn(npcId, x, y, z, heading, randomOffSet, despawnDelay);
 		if (npc.getId() == CHEST)
diff --git a/L2J_DataPack/dist/game/data/scripts/custom/events/Race/Race.java b/L2J_DataPack/dist/game/data/scripts/custom/events/Race/Race.java
index 5741066e76..4ffeab49b2 100644
--- a/L2J_DataPack/dist/game/data/scripts/custom/events/Race/Race.java
+++ b/L2J_DataPack/dist/game/data/scripts/custom/events/Race/Race.java
@@ -18,9 +18,8 @@
  */
 package custom.events.Race;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledFuture;
 
 import com.l2jserver.Config;
@@ -42,11 +41,11 @@ import com.l2jserver.gameserver.util.Broadcast;
 public final class Race extends Event
 {
 	// Event NPC's list
-	private List<L2Npc> _npclist;
+	private final Set<L2Npc> _npcs = ConcurrentHashMap.newKeySet();
 	// Npc
 	private L2Npc _npc;
 	// Player list
-	private List<L2PcInstance> _players;
+	private final Set<L2PcInstance> _players = ConcurrentHashMap.newKeySet();
 	// Event Task
 	ScheduledFuture<?> _eventTask = null;
 	// Event state
@@ -120,6 +119,7 @@ public final class Race extends Event
 		{
 			return false;
 		}
+		
 		// Check Custom Table - we use custom NPC's
 		if (!Config.CUSTOM_NPC_DATA)
 		{
@@ -127,9 +127,7 @@ public final class Race extends Event
 			eventMaker.sendMessage("Event " + getName() + " can't be started because custom NPC table is disabled!");
 			return false;
 		}
-		// Initialize list
-		_npclist = new ArrayList<>();
-		_players = new CopyOnWriteArrayList<>();
+		
 		// Set Event active
 		_isactive = true;
 		// Spawn Manager
@@ -167,7 +165,7 @@ public final class Race extends Event
 		// Transform players and send message
 		for (L2PcInstance player : _players)
 		{
-			if ((player != null) && player.isOnline())
+			if (player.isOnline())
 			{
 				if (player.isInsideRadius(_npc, 500, false, false))
 				{
@@ -209,22 +207,19 @@ public final class Race extends Event
 		// Teleport to event start point
 		for (L2PcInstance player : _players)
 		{
-			if ((player != null) && player.isOnline())
+			if (player.isOnline())
 			{
 				player.untransform();
 				player.teleToLocation(_npc.getX(), _npc.getY(), _npc.getZ(), true);
 			}
 		}
+		_players.clear();
 		// Despawn NPCs
-		for (L2Npc _npc : _npclist)
+		for (L2Npc _npc : _npcs)
 		{
-			if (_npc != null)
-			{
-				_npc.deleteMe();
-			}
+			_npc.deleteMe();
 		}
-		_npclist.clear();
-		_players.clear();
+		_npcs.clear();
 		// Announce event end
 		Broadcast.toAllOnlinePlayers("* Race Event finished *");
 		
@@ -355,10 +350,7 @@ public final class Race extends Event
 	private L2Npc recordSpawn(int npcId, int x, int y, int z, int heading, boolean randomOffSet, long despawnDelay)
 	{
 		final L2Npc npc = addSpawn(npcId, x, y, z, heading, randomOffSet, despawnDelay);
-		if (npc != null)
-		{
-			_npclist.add(npc);
-		}
+		_npcs.add(npc);
 		return npc;
 	}
 	
-- 
GitLab