Browse Source

BETA: Yeah, the ancient L2Event got reworked! Its now bulletproof against bugs :) You can now use it without worrying about bugs occuring cuz of it.

Nik 14 years ago
parent
commit
850398a886

+ 24 - 20
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -21,7 +21,6 @@ import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collection;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -265,6 +264,7 @@ import com.l2jserver.gameserver.templates.skills.L2EffectType;
 import com.l2jserver.gameserver.templates.skills.L2SkillType;
 import com.l2jserver.gameserver.util.FloodProtectors;
 import com.l2jserver.gameserver.util.Util;
+import com.l2jserver.util.PlayerEventStatus;
 import com.l2jserver.util.Point3D;
 import com.l2jserver.util.Rnd;
 
@@ -558,7 +558,7 @@ public final class L2PcInstance extends L2Playable
 	private boolean _recoTwoHoursGiven = false;
 	
 	private final PcInventory _inventory = new PcInventory(this);
-	private PcFreight _freight = new PcFreight(this);
+	private final PcFreight _freight = new PcFreight(this);
 	private PcWarehouse _warehouse;
 	private PcRefund _refund;
 	
@@ -729,16 +729,7 @@ public final class L2PcInstance extends L2Playable
 	public final ReentrantLock soulShotLock = new ReentrantLock();
 	
 	/** Event parameters */
-	public int eventX;
-	public int eventY;
-	public int eventZ;
-	public int eventkarma;
-	public int eventpvpkills;
-	public int eventpkkills;
-	public String eventTitle;
-	public LinkedList<String> kills = new LinkedList<String>();
-	public boolean eventSitForced = false;
-	public boolean atEvent = false;
+	private PlayerEventStatus eventStatus = null;
 	
 	private byte _handysBlockCheckerEventArena = -1;
 	
@@ -3142,9 +3133,9 @@ public final class L2PcInstance extends L2Playable
 	 */
 	public void standUp()
 	{
-		if (L2Event.active && eventSitForced)
+		if (L2Event.isParticipant(this) && getEventStatus().eventSitForced)
 		{
-			sendMessage("A dark force beyond your mortal understanding makes your knees to shake when you try to stand up ...");
+			sendMessage("A dark force beyond your mortal understanding makes your knees to shake when you try to stand up...");
 		}
 		else if (_waitTypeSitting && !isInStoreMode() && !isAlikeDead())
 		{
@@ -5369,10 +5360,8 @@ public final class L2PcInstance extends L2Playable
 			
 			TvTEvent.onKill(killer, this);
 			
-			if (atEvent && pk != null)
-			{
-				pk.kills.add(getName());
-			}
+			if (L2Event.isParticipant(pk) && pk != null)
+				pk.getEventStatus().kills.add(this);
 			
 			//announce pvp/pk
 			if (Config.ANNOUNCE_PK_PVP && pk != null && !pk.isGM())
@@ -5525,7 +5514,7 @@ public final class L2PcInstance extends L2Playable
 	
 	private void onDieDropItem(L2Character killer)
 	{
-		if (atEvent || killer == null)
+		if (L2Event.isParticipant(this) || killer == null)
 			return;
 		
 		L2PcInstance pk = killer.getActingPlayer();
@@ -5920,7 +5909,7 @@ public final class L2PcInstance extends L2Playable
 		
 		// Calculate the Experience loss
 		long lostExp = 0;
-		if (!atEvent)
+		if (!L2Event.isParticipant(this))
 			if (lvl < Experience.MAX_LEVEL)
 				lostExp = Math.round((getStat().getExpForLevel(lvl+1) - getStat().getExpForLevel(lvl)) * percentLost /100);
 			else
@@ -15156,4 +15145,19 @@ public final class L2PcInstance extends L2Playable
 	{
 		return _contactList;
 	}
+	
+	public void setEventStatus()
+	{
+		eventStatus = new PlayerEventStatus(this);
+	}
+	
+	public void setEventStatus(PlayerEventStatus pes)
+	{
+		eventStatus = pes;
+	}
+	
+	public PlayerEventStatus getEventStatus()
+	{
+		return eventStatus;
+	}
 }

+ 377 - 174
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/L2Event.java

@@ -19,192 +19,171 @@ import java.io.BufferedReader;
 import java.io.DataInputStream;
 import java.io.FileInputStream;
 import java.io.InputStreamReader;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javolution.util.FastList;
+import javolution.util.FastMap;
+
+import com.l2jserver.gameserver.cache.HtmCache;
 import com.l2jserver.gameserver.datatables.NpcTable;
 import com.l2jserver.gameserver.datatables.SpawnTable;
 import com.l2jserver.gameserver.model.L2Spawn;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.serverpackets.CharInfo;
+import com.l2jserver.gameserver.network.serverpackets.ExBrExtraUserInfo;
 import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
 import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
+import com.l2jserver.gameserver.network.serverpackets.UserInfo;
 import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
-import com.l2jserver.gameserver.util.Broadcast;
-import com.l2jserver.util.EventData;
-import com.l2jserver.util.StringUtil;
-
+import com.l2jserver.util.PlayerEventStatus;
+import com.l2jserver.util.ValueSortMap;
 
 /**
- * This class ...
- *
- * @version $Revision: 1.3.4.1 $ $Date: 2005/03/27 15:29:32 $
+ * @since $Revision: 1.3.4.1 $ $Date: 2005/03/27 15:29:32 $
+ * This ancient thingie got reworked by Nik at $Date: 2011/05/17 21:51:39 $
+ * Yeah, for 6 years no one bothered reworking this buggy event engine.
  */
 
 public class L2Event
 {
 	protected static final Logger _log = Logger.getLogger(L2Event.class.getName());
-	public static String eventName = "";
-	public static int teamsNumber = 0;
-	public static final HashMap<Integer, String> names = new HashMap<Integer, String>();
-	public static final LinkedList<String> participatingPlayers = new LinkedList<String>(); //TODO store by objid
-	public static final HashMap<Integer, LinkedList<String>> players = new HashMap<Integer, LinkedList<String>>();
-	public static int id = 12760;
-	public static final LinkedList<String> npcs = new LinkedList<String>();
-	public static boolean active = false;
-	public static final HashMap<String, EventData> connectionLossData = new HashMap<String, EventData>();
+	public static EventState eventState = EventState.OFF;
+	public static String _eventName = "";
+	public static String _eventCreator = "";
+	public static String _eventInfo = "";
+	public static int _teamsNumber = 0;
+	public static final Map<Integer, String> _teamNames = new FastMap<Integer, String>();
+	public static final List<L2PcInstance> _registeredPlayers = new FastList<L2PcInstance>();
+	public static final Map<Integer, FastList<L2PcInstance>> _teams = new FastMap<Integer, FastList<L2PcInstance>>();
+	public static int _npcId = 0;
+	//public static final List<L2Npc> _npcs = new FastList<L2Npc>();
+	private static final Map<L2PcInstance, PlayerEventStatus> _connectionLossData = new FastMap<L2PcInstance, PlayerEventStatus>();
 	
-	public static int getTeamOfPlayer(String name)
+	public enum EventState
 	{
-		for (int i = 1; i <= players.size(); i++)
+		OFF, // Not running
+		STANDBY, // Waiting for participants to register
+		ON // Registration is over and the event has started.
+	}
+	
+	/**
+	 * 
+	 * @param player
+	 * @return The team ID where the player is in, or -1 if player is null or team not found.
+	 */
+	public static int getPlayerTeamId(L2PcInstance player)
+	{
+		if (player == null)
+			return -1;
+		
+		for (Entry<Integer, FastList<L2PcInstance>> team : _teams.entrySet())
 		{
-			LinkedList<String> temp = players.get(i);
-			Iterator<String> it = temp.iterator();
-			while (it.hasNext())
-			{
-				if (it.next().equals(name))
-					return i;
-			}
+			if (team.getValue().contains(player))
+				return team.getKey();
 		}
-		return 0;
+		
+		return -1;
 	}
 	
-	public static String[] getTopNKillers(int N)
-	{ //this will return top N players sorted by kills, first element in the array will be the one with more kills
-		String[] killers = new String[N];
-		String playerTemp = "";
-		int kills = 0;
-		LinkedList<String> killersTemp = new LinkedList<String>();
+	public static List<L2PcInstance> getTopNKillers(int n)
+	{
+		Map<L2PcInstance, Integer> tmp = new FastMap<L2PcInstance, Integer>();
 		
-		for (int k = 0; k < N; k++)
+		for (FastList<L2PcInstance> teamList : _teams.values())
 		{
-			kills = 0;
-			for (int i = 1; i <= teamsNumber; i++)
+			for (L2PcInstance player : teamList)
 			{
-				LinkedList<String> temp = players.get(i);
-				Iterator<String> it = temp.iterator();
-				while (it.hasNext())
-				{
-					try
-					{
-						L2PcInstance player = L2World.getInstance().getPlayer(it.next());
-						if (!killersTemp.contains(player.getName()))
-						{
-							if (player.kills.size() > kills)
-							{
-								kills = player.kills.size();
-								playerTemp = player.getName();
-							}
-						}
-					}
-					catch (Exception e)
-					{
-					}
-				}
+				if (player.getEventStatus() == null)
+					continue;
+				
+				tmp.put(player, player.getEventStatus().kills.size());
 			}
-			killersTemp.add(playerTemp);
 		}
 		
-		for (int i = 0; i < N; i++)
+		ValueSortMap.sortMapByValue(tmp, false);
+		
+		// If the map size is less than "n", n will be as much as the map size
+		if (tmp.size() <= n)
 		{
-			kills = 0;
-			Iterator<String> it = killersTemp.iterator();
-			while (it.hasNext())
-			{
-				try
-				{
-					L2PcInstance player = L2World.getInstance().getPlayer(it.next());
-					if (player.kills.size() > kills)
-					{
-						kills = player.kills.size();
-						playerTemp = player.getName();
-					}
-				}
-				catch (Exception e)
-				{
-				}
-			}
-			killers[i] = playerTemp;
-			killersTemp.remove(playerTemp);
+			List<L2PcInstance> toReturn = new FastList<L2PcInstance>();
+			toReturn.addAll(tmp.keySet());
+			return toReturn;
+		}
+		else
+		{
+			List<L2PcInstance> toReturn = new FastList<L2PcInstance>();
+			toReturn.addAll(tmp.keySet());
+			return toReturn.subList(1, n);
 		}
-		return killers;
 	}
-	
+
 	public static void showEventHtml(L2PcInstance player, String objectid)
-	{
-		try
+	{//TODO: work on this
+		
+		if (eventState == EventState.STANDBY)
 		{
-			NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
-			
-			DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("data/events/" + eventName)));
-			BufferedReader inbr = new BufferedReader(new InputStreamReader(in));
-			
-			final StringBuilder replyMSG = new StringBuilder();
-			StringUtil.append(replyMSG,
-					"<html><body>" +
-					"<center><font color=\"LEVEL\">",
-					eventName,
-					"</font><font color=\"FF0000\"> bY ",
-					inbr.readLine(),
-					"</font></center><br>" +
-					"<br>",
-					inbr.readLine()
-			);
-			
-			if (L2Event.participatingPlayers.contains(player.getName())) {
-				replyMSG.append("<br><center>You are already in the event players list !!</center></body></html>");
-			} else {
-				StringUtil.append(replyMSG,
-						"<br><center><button value=\"Participate !! \" action=\"bypass -h npc_",
-						String.valueOf(objectid),
-						"_event_participate\" width=90 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></center></body></html>"
-				);
+			try
+			{
+				final String htmContent;
+				NpcHtmlMessage html = new NpcHtmlMessage(5);
+				
+				if (_registeredPlayers.contains(player))
+					htmContent = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/mods/EventEngine/Participating.htm");
+				else
+					htmContent = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/mods/EventEngine/Participation.htm");
+				
+				if (htmContent != null)
+					html.setHtml(htmContent);
+				
+				html.replace("%objectId%", objectid); // Yeah, we need this.
+				html.replace("%eventName%", _eventName);
+				html.replace("%eventCreator%", _eventCreator);
+				html.replace("%eventInfo%", _eventInfo);
+				player.sendPacket(html);
+			}
+			catch (Exception e)
+			{
+				_log.log(Level.WARNING, "Exception on showEventHtml(): " + e.getMessage(), e);
 			}
-			
-			adminReply.setHtml(replyMSG.toString());
-			player.sendPacket(adminReply);
-		}
-		catch (Exception e)
-		{
-			_log.log(Level.WARNING, "Exception on showEventHtml(): " + e.getMessage(), e);
 		}
 	}
 	
-	public static void spawn(L2PcInstance target, int npcid)
+	/**
+	 * Spawns an event participation NPC near the player.
+	 * The npc id used to spawning is L2Event._npcId
+	 */
+	public static void spawnEventNpc(L2PcInstance target)
 	{
 		
-		L2NpcTemplate template1 = NpcTable.getInstance().getTemplate(npcid);
+		L2NpcTemplate template = NpcTable.getInstance().getTemplate(_npcId);
 		
 		try
 		{
-			//L2MonsterInstance mob = new L2MonsterInstance(template1);
-			
-			L2Spawn spawn = new L2Spawn(template1);
+			L2Spawn spawn = new L2Spawn(template);
 			
 			spawn.setLocx(target.getX() + 50);
 			spawn.setLocy(target.getY() + 50);
 			spawn.setLocz(target.getZ());
 			spawn.setAmount(1);
 			spawn.setHeading(target.getHeading());
-			spawn.setRespawnDelay(1);
 			
 			SpawnTable.getInstance().addNewSpawn(spawn, false);
 			
 			spawn.init();
 			spawn.getLastSpawn().setCurrentHp(999999999);
-			spawn.getLastSpawn().setName("event inscriptor");
-			spawn.getLastSpawn().setTitle(L2Event.eventName);
+			spawn.getLastSpawn().setTitle(_eventName);
 			spawn.getLastSpawn().isEventMob = true;
-			spawn.getLastSpawn().isAggressive();
-			spawn.getLastSpawn().decayMe();
-			spawn.getLastSpawn().spawnMe(spawn.getLastSpawn().getX(), spawn.getLastSpawn().getY(), spawn.getLastSpawn().getZ());
+			//spawn.getLastSpawn().decayMe();
+			//spawn.getLastSpawn().spawnMe(spawn.getLastSpawn().getX(), spawn.getLastSpawn().getY(), spawn.getLastSpawn().getZ());
 			
 			spawn.getLastSpawn().broadcastPacket(new MagicSkillUse(spawn.getLastSpawn(), spawn.getLastSpawn(), 1034, 1, 1, 1));
 			
-			npcs.add(String.valueOf(spawn.getLastSpawn().getObjectId()));
+			//_npcs.add(spawn.getLastSpawn());
 			
 		}
 		catch (Exception e)
@@ -214,88 +193,312 @@ public class L2Event
 		
 	}
 	
-	public static void announceAllPlayers(String text)
+	public static void unspawnEventNpcs()
 	{
-		Broadcast.announceToOnlinePlayers(text);
+		//Its a little rough, but for sure it will remove every damn event NPC.
+		for (L2Spawn spawn : SpawnTable.getInstance().getSpawnTable())
+		{
+			if (spawn.getLastSpawn() != null && spawn.getLastSpawn().isEventMob)
+			{
+				spawn.getLastSpawn().deleteMe();
+				spawn.stopRespawn();
+				SpawnTable.getInstance().deleteSpawn(spawn, false);
+			}
+		}
+		//for (L2Npc npc : _npcs)
+		//	npc.deleteMe();
 	}
 	
-	public static boolean isOnEvent(L2PcInstance player)
+	/**
+	 * 
+	 * @return False: If player is null, his event status is null or the event state is off.
+	 * True: if the player is inside the _registeredPlayers list while the event state is STANDBY.
+	 * If the event state is ON, it will check if the player is inside in one of the teams.
+	 */
+	public static boolean isParticipant(L2PcInstance player)
 	{
+		if (player == null || player.getEventStatus() == null)
+			return false;
 		
-		for (int k = 0; k < L2Event.teamsNumber; k++)
+		switch (eventState)
 		{
-			Iterator<String> it = L2Event.players.get(k + 1).iterator();
-			boolean temp = false;
-			while (it.hasNext())
-			{
-				temp = player.getName().equalsIgnoreCase(it.next());
-				if (temp)
-					return true;
-			}
+			case OFF:
+				return false;
+			case STANDBY:
+				return _registeredPlayers.contains(player);
+			case ON:
+				for (FastList<L2PcInstance> teamList : _teams.values())
+				{
+					if (teamList.contains(player))
+						return true;
+				}
 		}
 		return false;
 		
 	}
 	
-	public static void inscribePlayer(L2PcInstance player)
+	/**
+	 * 
+	 * Adds the player to the list of participants.
+	 * If the event state is NOT STANDBY, the player wont be registered.
+	 */
+	public static void registerPlayer(L2PcInstance player)
+	{
+		if (eventState != EventState.STANDBY)
+		{
+			player.sendMessage("The registration period for this event is over.");
+			return;
+		}
+		
+		_registeredPlayers.add(player);
+	}
+	
+	/**
+	 * 
+	 * Removes the player from the participating players and the teams and restores
+	 * his init stats before he registered at the event (loc, pvp, pk, title etc)
+	 */
+	public static void removeAndResetPlayer(L2PcInstance player)
 	{
 		
 		try
-		{
-			L2Event.participatingPlayers.add(player.getName());
-			player.eventkarma = player.getKarma();
-			player.eventX = player.getX();
-			player.eventY = player.getY();
-			player.eventZ = player.getZ();
-			player.eventpkkills = player.getPkKills();
-			player.eventpvpkills = player.getPvpKills();
-			player.eventTitle = player.getTitle();
-			player.kills.clear();
-			player.atEvent = true;
+		{			
+			if (isParticipant(player))
+			{
+				if (player.isDead())
+				{
+					player.restoreExp(100.0);
+					player.doRevive();
+					player.setCurrentHpMp(player.getMaxHp(), player.getMaxMp());
+					player.setCurrentCp(player.getMaxCp());
+				}
+				
+				player.getPoly().setPolyInfo(null, "1");
+				player.decayMe();
+				player.spawnMe(player.getX(), player.getY(), player.getZ());
+				CharInfo info1 = new CharInfo(player);
+				player.broadcastPacket(info1);
+				UserInfo info2 = new UserInfo(player);
+				player.sendPacket(info2);
+				player.broadcastPacket(new ExBrExtraUserInfo(player));
+				
+				player.stopTransformation(true);
+			}
+			
+			if (player.getEventStatus() != null)
+				player.getEventStatus().restoreInits();
+			
+			player.setEventStatus(null);
+			
+			_registeredPlayers.remove(player);
+			int teamId = getPlayerTeamId(player);
+			if (_teams.containsKey(teamId))
+				_teams.get(teamId).remove(player);
 		}
 		catch (Exception e)
 		{
-			_log.log(Level.WARNING, "Error when signing in the event:" + e.getMessage(), e);
+			_log.log(Level.WARNING, "Error at unregisterAndResetPlayer in the event:" + e.getMessage(), e);
+		}
+	}
+	
+	/**
+	 * 
+	 * The player's event status will be saved at _connectionLossData
+	 */
+	public static void savePlayerEventStatus(L2PcInstance player)
+	{
+			_connectionLossData.put(player, player.getEventStatus());
+	}
+	
+	/**
+	 * 
+	 * If _connectionLossData contains the player, it will restore the player's event status.
+	 * Also it will remove the player from the _connectionLossData.
+	 */
+	public static void restorePlayerEventStatus(L2PcInstance player)
+	{
+		if (_connectionLossData.containsKey(player))
+		{
+			player.setEventStatus(_connectionLossData.get(player));
+			_connectionLossData.remove(player);
 		}
 	}
 	
-	public static void restoreChar(L2PcInstance player)
+	/**
+	 * If the event is ON or STANDBY, it will not start.
+	 * Sets the event state to STANDBY and spawns registration NPCs
+	 * @return a string with information if the event participation has been successfully started or not.
+	 */
+	public static String startEventParticipation()
 	{
 		try
 		{
-			player.eventX = connectionLossData.get(player.getName()).eventX;
-			player.eventY = connectionLossData.get(player.getName()).eventY;
-			player.eventZ = connectionLossData.get(player.getName()).eventZ;
-			player.eventkarma = connectionLossData.get(player.getName()).eventKarma;
-			player.eventpvpkills = connectionLossData.get(player.getName()).eventPvpKills;
-			player.eventpkkills = connectionLossData.get(player.getName()).eventPkKills;
-			player.eventTitle = connectionLossData.get(player.getName()).eventTitle;
-			player.kills = connectionLossData.get(player.getName()).kills;
-			player.eventSitForced = connectionLossData.get(player.getName()).eventSitForced;
-			player.atEvent = true;
+			switch (eventState)
+			{
+				case ON:
+					return "Cannot start event, it is already on.";
+				case STANDBY:
+					return "Cannot start event, it is on standby mode.";
+				case OFF: // Event is off, so no problem turning it on.
+					eventState = EventState.STANDBY;
+					break;
+			}
+			
+			// Just in case
+			unspawnEventNpcs();
+			_registeredPlayers.clear();
+			//_npcs.clear();
+			
+			if (NpcTable.getInstance().getTemplate(_npcId) == null)
+				return "Cannot start event, invalid npc id.";
+			
+			DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("data/events/" + _eventName)));
+			BufferedReader inbr = new BufferedReader(new InputStreamReader(in));
+			_eventCreator = inbr.readLine();
+			_eventInfo = inbr.readLine();
+			
+			List<L2PcInstance> temp = new FastList<L2PcInstance>();
+			for (L2PcInstance player : L2World.getInstance().getAllPlayers().values())
+			{
+				if (!player.isOnline()) // Offline shops? 
+					continue;
+				
+				if (!temp.contains(player))
+				{
+					spawnEventNpc(player);
+					temp.add(player);
+				}
+				for (L2PcInstance playertemp : player.getKnownList().getKnownPlayers().values())
+				{
+					if ((Math.abs(playertemp.getX() - player.getX()) < 1000) && (Math.abs(playertemp.getY() - player.getY()) < 1000) && (Math.abs(playertemp.getZ() - player.getZ()) < 1000))
+						temp.add(playertemp);
+				}
+			}	
 		}
 		catch (Exception e)
 		{
+			e.printStackTrace();
+			return "Cannot start event participation, an error has occured.";
 		}
+		
+		return "The event participation has been successfully started.";
 	}
 	
-	public static void restoreAndTeleChar(L2PcInstance target)
+	/**
+	 * If the event is ON or OFF, it will not start.
+	 * Sets the event state to ON, creates the teams, 
+	 * adds the registered players ordered by level at the teams
+	 * and adds a new event status to the players.
+	 * @return a string with information if the event has been successfully started or not.
+	 */
+	public static String startEvent()
 	{
-		
 		try
 		{
-			restoreChar(target);
-			target.setTitle(target.eventTitle);
-			target.setKarma(target.eventkarma);
-			target.setPvpKills(target.eventpvpkills);
-			target.setPkKills(target.eventpkkills);
-			target.teleToLocation(target.eventX, target.eventY, target.eventZ, true);
-			target.kills.clear();
-			target.eventSitForced = false;
-			target.atEvent = false;
+			switch (eventState)
+			{
+				case ON:
+					return "Cannot start event, it is already on.";
+				case STANDBY:
+					eventState = EventState.ON;
+					break;
+				case OFF: // Event is off, so no problem turning it on.
+					return "Cannot start event, it is off. Participation start is required.";
+			}
+			
+			// Clean the things we will use, just in case.
+			unspawnEventNpcs();
+			_teams.clear();
+			_connectionLossData.clear();
+			
+			// Insert empty lists at _teams.
+			for (int i = 0; i < _teamsNumber; i++)
+				_teams.put(i + 1, new FastList<L2PcInstance>());
+			
+			int i = 0;
+			while (!_registeredPlayers.isEmpty())
+			{
+				//Get the player with the biggest level
+				int max = 0;
+				L2PcInstance biggestLvlPlayer = null;
+				for (L2PcInstance player : _registeredPlayers)
+				{
+						if (player == null)
+							continue;
+						
+						if (max < player.getLevel())
+						{
+							max = player.getLevel();
+							biggestLvlPlayer = player;
+						}
+				}
+				
+				if (biggestLvlPlayer == null)
+					continue;
+				
+				_registeredPlayers.remove(biggestLvlPlayer);
+				_teams.get(i + 1).add(biggestLvlPlayer);
+				biggestLvlPlayer.setEventStatus();
+				i = (i + 1) % _teamsNumber;
+			}
+			
 		}
 		catch (Exception e)
 		{
+			e.printStackTrace();
+			return "Cannot start event, an error has occured.";
 		}
+		
+		return "The event has been successfully started.";
+	}
+	
+	/**
+	 * If the event state is OFF, it will not finish.
+	 * Sets the event state to OFF, unregisters and resets the players,
+	 * unspawns and clers the event NPCs, clears the teams, registered players,
+	 * connection loss data, sets the teams number to 0, sets the event name to empty.
+	 * @return a string with information if the event has been successfully stopped or not.
+	 */
+	public static String finishEvent()
+	{
+			switch (eventState)
+			{
+				case OFF:
+					return "Cannot finish event, it is already off.";
+				case STANDBY:
+					for (L2PcInstance player : _registeredPlayers)
+						removeAndResetPlayer(player);
+					
+					unspawnEventNpcs();
+					//_npcs.clear();
+					_registeredPlayers.clear();
+					_teams.clear();
+					_connectionLossData.clear();
+					_teamsNumber = 0;
+					_eventName = "";
+					eventState = EventState.OFF;
+					return "The event has been stopped at STANDBY mode, all players unregistered and all event npcs unspawned.";
+				case ON:
+					for (FastList<L2PcInstance> teamList : _teams.values())
+					{
+						for (L2PcInstance player : teamList)
+							removeAndResetPlayer(player);
+					}
+					
+					eventState = EventState.OFF;
+					unspawnEventNpcs(); // Just in case
+					//_npcs.clear();
+					_registeredPlayers.clear();
+					_teams.clear();
+					_connectionLossData.clear();
+					_teamsNumber = 0;
+					_eventName = "";
+					_npcId = 0;
+					_eventCreator = "";
+					_eventInfo = "";
+					return "The event has been stopped, all players unregistered and all event npcs unspawned.";
+			}
+		
+		return "The event has been successfully finished.";
 	}
 }

+ 7 - 10
L2J_Server_BETA/java/com/l2jserver/gameserver/network/L2GameClient.java

@@ -52,7 +52,6 @@ import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
 import com.l2jserver.gameserver.network.serverpackets.ServerClose;
 import com.l2jserver.gameserver.util.FloodProtectors;
 import com.l2jserver.gameserver.util.Util;
-import com.l2jserver.util.EventData;
 
 /**
  * Represents a client connected on Game Server
@@ -78,10 +77,10 @@ public final class L2GameClient extends MMOClient<MMOConnection<L2GameClient>> i
 	private String _accountName;
 	private SessionKey _sessionId;
 	private L2PcInstance _activeChar;
-	private ReentrantLock _activeCharLock = new ReentrantLock();
+	private final ReentrantLock _activeCharLock = new ReentrantLock();
 	
 	private boolean _isAuthedGG;
-	private long _connectionStartTime;
+	private final long _connectionStartTime;
 	private CharSelectInfoPackage[] _charSlotMapping = null;
 	
 	// floodprotectors
@@ -94,16 +93,16 @@ public final class L2GameClient extends MMOClient<MMOConnection<L2GameClient>> i
 	private L2GameServerPacket _aditionalClosePacket;
 	
 	// Crypt
-	private GameCrypt _crypt;
+	private final GameCrypt _crypt;
 	
-	private ClientStats _stats;
+	private final ClientStats _stats;
 	
 	private boolean _isDetached = false;
 	
 	private boolean _protocol;
 	
 	private final ArrayBlockingQueue<ReceivablePacket<L2GameClient>> _packetQueue;
-	private ReentrantLock _queueLock = new ReentrantLock();
+	private final ReentrantLock _queueLock = new ReentrantLock();
 	
 	private int[][] trace;
 	
@@ -796,11 +795,9 @@ public final class L2GameClient extends MMOClient<MMOConnection<L2GameClient>> i
 					}
 					
 					// we store all data from players who are disconnected while in an event in order to restore it in the next login
-					if (player.atEvent)
+					if (L2Event.isParticipant(player))
 					{
-						EventData data = new EventData(player.eventX, player.eventY, player.eventZ, player.eventkarma, player.eventpvpkills, player.eventpkkills, player.eventTitle, player.kills,
-								player.eventSitForced);
-						L2Event.connectionLossData.put(player.getName(), data);
+						L2Event.savePlayerEventStatus(player);
 					}
 
 					// prevent closing again

+ 3 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java

@@ -102,7 +102,7 @@ public class EnterWorld extends L2GameClientPacket
 	
 	private static Logger _log = Logger.getLogger(EnterWorld.class.getName());
 	
-	private int[][] tracert = new int[5][4];
+	private final int[][] tracert = new int[5][4];
 	
 	public TaskPriority getPriority()
 	{
@@ -336,10 +336,8 @@ public class EnterWorld extends L2GameClientPacket
 		
 		activeChar.spawnMe(activeChar.getX(), activeChar.getY(), activeChar.getZ());
 		
-		if (L2Event.active && L2Event.connectionLossData.containsKey(activeChar.getName()) && L2Event.isOnEvent(activeChar))
-			L2Event.restoreChar(activeChar);
-		else if (L2Event.connectionLossData.containsKey(activeChar.getName()))
-			L2Event.restoreAndTeleChar(activeChar);
+		if (L2Event.isParticipant(activeChar))
+			L2Event.restorePlayerEventStatus(activeChar);
 		
 		// Wedding Checks
 		if (Config.L2JMOD_ALLOW_WEDDING)

+ 2 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/Logout.java

@@ -22,6 +22,7 @@ import com.l2jserver.Config;
 import com.l2jserver.gameserver.SevenSignsFestival;
 import com.l2jserver.gameserver.model.L2Party;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.entity.L2Event;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
@@ -76,7 +77,7 @@ public final class Logout extends L2GameClientPacket
 			return;
 		}
 		
-		if(player.atEvent)
+		if(L2Event.isParticipant(player))
 		{
 			player.sendMessage("A superior power doesn't allow you to leave the event");
 			player.sendPacket(ActionFailed.STATIC_PACKET);

+ 1 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestBypassToServer.java

@@ -33,7 +33,6 @@ import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2MerchantSummonInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.entity.Hero;
-import com.l2jserver.gameserver.model.entity.L2Event;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.communityserver.CommunityServerThread;
 import com.l2jserver.gameserver.network.communityserver.writepackets.RequestShowCommunityBoard;
@@ -138,9 +137,7 @@ public final class RequestBypassToServer extends L2GameClientPacket
 				{
 					L2Object object = L2World.getInstance().findObject(Integer.parseInt(id));
 					
-					if (_command.substring(endOfId+1).startsWith("event_participate"))
-						L2Event.inscribePlayer(activeChar);
-					else if (object instanceof L2Npc && endOfId > 0 && activeChar.isInsideRadius(object, L2Npc.INTERACTION_DISTANCE, false, false))
+					if (object instanceof L2Npc && endOfId > 0 && activeChar.isInsideRadius(object, L2Npc.INTERACTION_DISTANCE, false, false))
 						((L2Npc)object).onBypassFeedback(activeChar, _command.substring(endOfId+1));
 					
 					activeChar.sendPacket(ActionFailed.STATIC_PACKET);

+ 0 - 52
L2J_Server_BETA/java/com/l2jserver/util/EventData.java

@@ -1,52 +0,0 @@
-/*
- * $Header: EventData.java
- *
- * $Author: SarEvoK
- * Added copyright notice
- *
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.l2jserver.util;
-
-import java.util.LinkedList;
-
-public class EventData
-{
-	public int eventX;
-	public int eventY;
-	public int eventZ;
-	public int eventKarma;
-	public int eventPvpKills;
-	public int eventPkKills;
-	public String eventTitle;
-	public LinkedList<String> kills = new LinkedList<String>();
-	public boolean eventSitForced = false;
-	
-	public EventData(int pEventX, int pEventY, int pEventZ, int pEventkarma, int pEventpvpkills,
-			int pEventpkkills, String pEventTitle, LinkedList<String> pKills,
-			boolean pEventSitForced)
-	{
-		eventX = pEventX;
-		eventY = pEventY;
-		eventZ = pEventZ;
-		eventKarma = pEventkarma;
-		eventPvpKills = pEventpvpkills;
-		eventPkKills = pEventpkkills;
-		eventTitle = pEventTitle;
-		kills = pKills;
-		eventSitForced = pEventSitForced;
-	}
-}

+ 63 - 0
L2J_Server_BETA/java/com/l2jserver/util/PlayerEventStatus.java

@@ -0,0 +1,63 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.util;
+
+import java.util.List;
+
+import javolution.util.FastList;
+
+import com.l2jserver.gameserver.instancemanager.InstanceManager;
+import com.l2jserver.gameserver.model.Location;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+
+/**
+ * @author Nik
+ */
+
+public class PlayerEventStatus
+{
+	public L2PcInstance player = null;
+	public Location initLoc = new Location(0,0,0);
+	public int initInstanceId = 0;
+	public int initKarma = 0;
+	public int initPvpKills = 0;
+	public int initPkKills = 0;
+	public String initTitle = "";
+	public List<L2PcInstance> kills = new FastList<L2PcInstance>();
+	public boolean eventSitForced = false;
+	
+	public PlayerEventStatus(L2PcInstance player)
+	{
+		this.player = player;
+		initLoc = new Location(player.getX(), player.getY(), player.getZ(), player.getHeading());
+		initInstanceId = player.getInstanceId();
+		initKarma = player.getKarma();
+		initPvpKills = player.getPvpKills();
+		initPkKills = player.getPkKills();
+		initTitle = player.getTitle();
+		
+	}
+	
+	public void restoreInits()
+	{
+		player.teleToLocation(initLoc, true);
+		if (initInstanceId > 0 && InstanceManager.getInstance().getInstance(initInstanceId) != null)
+			player.setInstanceId(initInstanceId);
+		player.setKarma(initKarma);
+		player.setPvpKills(initPvpKills);
+		player.setPkKills(initPkKills);
+		player.setTitle(initTitle);
+	}
+}