Browse Source

New floodprotector added: CharacterSelect.
Protected packets: CharacterSelect, CharacterDelete, CharacterRestore. Timeout 3s.
Floodprotectors moved to L2PcInstance, logging reworked.

_DS_ 15 years ago
parent
commit
1dbc6b5b52

+ 18 - 26
L2_GameServer/java/com/l2jserver/Config.java

@@ -566,30 +566,19 @@ public final class Config
 	//--------------------------------------------------
 	//--------------------------------------------------
 	// FloodProtector Settings
 	// FloodProtector Settings
 	//--------------------------------------------------
 	//--------------------------------------------------
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_USE_ITEM;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_ROLL_DICE;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_FIREWORK;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_ITEM_PET_SUMMON;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_HERO_VOICE;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_GLOBAL_CHAT;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_SUBCLASS;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_DROP_ITEM;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_SERVER_BYPASS;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_MULTISELL;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_TRANSACTION;
-		
-	public static  FloodProtectorConfig FLOOD_PROTECTOR_SENDMAIL;
-		
+	public static FloodProtectorConfig FLOOD_PROTECTOR_USE_ITEM;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_ROLL_DICE;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_FIREWORK;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_ITEM_PET_SUMMON;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_HERO_VOICE;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_GLOBAL_CHAT;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_SUBCLASS;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_DROP_ITEM;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_SERVER_BYPASS;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_MULTISELL;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_TRANSACTION;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_SENDMAIL;
+	public static FloodProtectorConfig FLOOD_PROTECTOR_CHARACTER_SELECT;
 
 
 
 
 	//--------------------------------------------------
 	//--------------------------------------------------
@@ -1006,7 +995,9 @@ public final class Config
 				new FloodProtectorConfig("TransactionFloodProtector");
 				new FloodProtectorConfig("TransactionFloodProtector");
 			FLOOD_PROTECTOR_SENDMAIL =
 			FLOOD_PROTECTOR_SENDMAIL =
 				new FloodProtectorConfig("SendMailFloodProtector");
 				new FloodProtectorConfig("SendMailFloodProtector");
-			
+			FLOOD_PROTECTOR_CHARACTER_SELECT =
+				new FloodProtectorConfig("CharacterSelectFloodProtector");
+
 			_log.info("Loading GameServer Configuration Files...");
 			_log.info("Loading GameServer Configuration Files...");
 			InputStream is = null;
 			InputStream is = null;
 			try
 			try
@@ -3014,7 +3005,8 @@ public final class Config
 		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_SERVER_BYPASS, "ServerBypass", "5");
 		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_SERVER_BYPASS, "ServerBypass", "5");
 		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_MULTISELL, "MultiSell", "1");
 		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_MULTISELL, "MultiSell", "1");
 		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_TRANSACTION, "Transaction", "10");
 		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_TRANSACTION, "Transaction", "10");
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_SENDMAIL, "SendMail", "600");
+		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_SENDMAIL, "SendMail", "100");
+		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_CHARACTER_SELECT, "CharacterSelect", "30");
 	}
 	}
 	
 	
 	/**
 	/**

+ 1 - 3
L2_GameServer/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -450,8 +450,6 @@ public final class L2PcInstance extends L2Playable
 	
 	
 	public FastList<TeleportBookmark> tpbookmark = new FastList<TeleportBookmark>();
 	public FastList<TeleportBookmark> tpbookmark = new FastList<TeleportBookmark>();
 	
 	
-	private final FloodProtectors _floodProtectors = new FloodProtectors(this);
-
     private PunishLevel _punishLevel = PunishLevel.NONE;
     private PunishLevel _punishLevel = PunishLevel.NONE;
 	private long _punishTimer = 0;
 	private long _punishTimer = 0;
 	private ScheduledFuture<?> _punishTask;
 	private ScheduledFuture<?> _punishTask;
@@ -13895,7 +13893,7 @@ public final class L2PcInstance extends L2Playable
     
     
     public FloodProtectors getFloodProtectors()
     public FloodProtectors getFloodProtectors()
     {
     {
-    	return _floodProtectors;
+    	return getClient().getFloodProtectors();
     }
     }
 
 
     public boolean isFlyingMounted()
     public boolean isFlyingMounted()

+ 9 - 0
L2_GameServer/java/com/l2jserver/gameserver/network/L2GameClient.java

@@ -47,6 +47,7 @@ import com.l2jserver.gameserver.model.entity.L2Event;
 import com.l2jserver.gameserver.model.entity.TvTEvent;
 import com.l2jserver.gameserver.model.entity.TvTEvent;
 import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
 import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
 import com.l2jserver.gameserver.network.serverpackets.ServerClose;
 import com.l2jserver.gameserver.network.serverpackets.ServerClose;
+import com.l2jserver.gameserver.util.FloodProtectors;
 import com.l2jserver.gameserver.util.Util;
 import com.l2jserver.gameserver.util.Util;
 import com.l2jserver.util.EventData;
 import com.l2jserver.util.EventData;
 
 
@@ -79,6 +80,9 @@ public final class L2GameClient extends MMOClient<MMOConnection<L2GameClient>>
 	private long _connectionStartTime;
 	private long _connectionStartTime;
 	private List<Integer> _charSlotMapping = new FastList<Integer>();
 	private List<Integer> _charSlotMapping = new FastList<Integer>();
 
 
+	// floodprotectors
+	private final FloodProtectors _floodProtectors = new FloodProtectors(this);
+
 	// Task
 	// Task
 	protected final ScheduledFuture<?> _autoSaveInDB;
 	protected final ScheduledFuture<?> _autoSaveInDB;
 	protected ScheduledFuture<?> _cleanupTask = null;
 	protected ScheduledFuture<?> _cleanupTask = null;
@@ -174,6 +178,11 @@ public final class L2GameClient extends MMOClient<MMOConnection<L2GameClient>>
 		return _activeCharLock;
 		return _activeCharLock;
 	}
 	}
 
 
+	public FloodProtectors getFloodProtectors()
+	{
+		return _floodProtectors;
+	}
+
 	public void setGameGuardOk(boolean val)
 	public void setGameGuardOk(boolean val)
 	{
 	{
 		_isAuthedGG = val;
 		_isAuthedGG = val;

+ 3 - 0
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/CharacterDelete.java

@@ -46,6 +46,9 @@ public final class CharacterDelete extends L2GameClientPacket
 	@Override
 	@Override
 	protected void runImpl()
 	protected void runImpl()
 	{
 	{
+		if (!getClient().getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterDelete"))
+			return;
+
 		if (Config.DEBUG) _log.fine("deleting slot:" + _charSlot);
 		if (Config.DEBUG) _log.fine("deleting slot:" + _charSlot);
 		
 		
 		try
 		try

+ 3 - 0
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/CharacterRestore.java

@@ -38,6 +38,9 @@ public final class CharacterRestore extends L2GameClientPacket
 	@Override
 	@Override
 	protected void runImpl()
 	protected void runImpl()
 	{
 	{
+		if (!getClient().getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterRestore"))
+			return;
+
 	    try
 	    try
 	    {
 	    {
 		getClient().markRestoredChar(_charSlot);
 		getClient().markRestoredChar(_charSlot);

+ 2 - 95
L2_GameServer/java/com/l2jserver/gameserver/network/clientpackets/CharacterSelect.java

@@ -64,13 +64,8 @@ public class CharacterSelect extends L2GameClientPacket
 	@Override
 	@Override
     protected void runImpl()
     protected void runImpl()
 	{
 	{
-		// if there is a playback.dat file in the current directory, it will
-		// be sent to the client instead of any regular packets
-		// to make this work, the first packet in the playback.dat has to
-		// be a  [S]0x21 packet
-		// after playback is done, the client will not work correct and need to exit
-		//playLogFile(getConnection()); // try to play log file
-
+		if (!getClient().getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterSelect"))
+			return;
 
 
 		// we should always be abble to acquire the lock
 		// we should always be abble to acquire the lock
 		// but if we cant lock then nothing should be done (ie repeated packet)
 		// but if we cant lock then nothing should be done (ie repeated packet)
@@ -125,94 +120,6 @@ public class CharacterSelect extends L2GameClientPacket
 		}
 		}
 	}
 	}
 
 
-	/*
-	private void playLogFile(Connection connection)
-	{
-		long diff = 0;
-		long first = -1;
-
-		try
-		{
-			LineNumberReader lnr =
-			new LineNumberReader(new FileReader("playback.dat"));
-
-			String line = null;
-			while ((line = lnr.readLine()) != null)
-			{
-				if (line.length() > 0 && line.substring(0, 1).equals("1"))
-				{
-					String timestamp = line.substring(0, 13);
-					long time = Long.parseLong(timestamp);
-					if (first == -1)
-					{
-						long start = System.currentTimeMillis();
-						first = time;
-						diff = start - first;
-					}
-
-					String cs = line.substring(14, 15);
-					// read packet definition
-					ByteArrayOutputStream bais = new ByteArrayOutputStream();
-
-					while (true)
-					{
-						String temp = lnr.readLine();
-						if (temp.length() < 53)
-						{
-							break;
-						}
-
-						String bytes = temp.substring(6, 53);
-						StringTokenizer st = new StringTokenizer(bytes);
-						while (st.hasMoreTokens())
-						{
-							String b = st.nextToken();
-							int number = Integer.parseInt(b, 16);
-							bais.write(number);
-						}
-					}
-
-					if (cs.equals("S"))
-					{
-						//wait for timestamp and send packet
-						int wait =
-						(int) (time + diff - System.currentTimeMillis());
-						if (wait > 0)
-						{
-							if (Config.DEBUG) _log.fine("waiting"+ wait);
-							Thread.sleep(wait);
-						}
-						if (Config.DEBUG) _log.fine("sending:"+ time);
-						byte[] data = bais.toByteArray();
-						if (data.length != 0)
-						{
-							//connection.sendPacket(data);	
-						}
-						else
-						{
-							if (Config.DEBUG) _log.fine("skipping broken data");
-						}
-
-					}
-					else
-					{
-						// skip packet
-					}
-				}
-
-			}
-		}
-		catch (FileNotFoundException f)
-		{
-			// should not happen
-		}
-		catch (Exception e)
-		{
-			_log.log(Level.SEVERE, "Error:", e);
-		}
-	}
-	 */
-
 	/* (non-Javadoc)
 	/* (non-Javadoc)
 	 * @see com.l2jserver.gameserver.clientpackets.ClientBasePacket#getType()
 	 * @see com.l2jserver.gameserver.clientpackets.ClientBasePacket#getType()
 	 */
 	 */

+ 69 - 19
L2_GameServer/java/com/l2jserver/gameserver/util/FloodProtectorAction.java

@@ -18,6 +18,7 @@ import java.util.logging.Logger;
 
 
 import com.l2jserver.gameserver.GameTimeController;
 import com.l2jserver.gameserver.GameTimeController;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.L2GameClient;
 import com.l2jserver.util.StringUtil;
 import com.l2jserver.util.StringUtil;
 
 
 /**
 /**
@@ -33,9 +34,9 @@ public final class FloodProtectorAction
 	 */
 	 */
 	private static final Logger _log = Logger.getLogger(FloodProtectorAction.class.getName());
 	private static final Logger _log = Logger.getLogger(FloodProtectorAction.class.getName());
 	/**
 	/**
-	 * Player for this instance of flood protector.
+	 * Client for this instance of flood protector.
 	 */
 	 */
-	private final L2PcInstance _player;
+	private final L2GameClient _client;
 	/**
 	/**
 	 * Configuration of this instance of flood protector.
 	 * Configuration of this instance of flood protector.
 	 */
 	 */
@@ -66,13 +67,13 @@ public final class FloodProtectorAction
 	 * @param config
 	 * @param config
 	 *            flood protector configuration
 	 *            flood protector configuration
 	 */
 	 */
-	public FloodProtectorAction(final L2PcInstance player, final FloodProtectorConfig config)
+	public FloodProtectorAction(final L2GameClient client, final FloodProtectorConfig config)
 	{
 	{
 		super();
 		super();
-		_player = player;
+		_client = client;
 		_config = config;
 		_config = config;
 	}
 	}
-	
+
 	/**
 	/**
 	 * Checks whether the request is flood protected or not.
 	 * Checks whether the request is flood protected or not.
 	 * 
 	 * 
@@ -89,7 +90,7 @@ public final class FloodProtectorAction
 		{
 		{
 			if (_config.LOG_FLOODING && !_logged && _log.isLoggable(Level.WARNING))
 			if (_config.LOG_FLOODING && !_logged && _log.isLoggable(Level.WARNING))
 			{
 			{
-				_log.warning(StringUtil.concat(_config.FLOOD_PROTECTOR_TYPE, ": Player [", _player.getName(), "] called command [", command, "] [~", String.valueOf((_config.FLOOD_PROTECTION_INTERVAL - (_nextGameTick - curTick)) * GameTimeController.MILLIS_IN_TICK), " ms] after previous command"));
+				log(" called command ", command, " ~", String.valueOf((_config.FLOOD_PROTECTION_INTERVAL - (_nextGameTick - curTick)) * GameTimeController.MILLIS_IN_TICK), " ms after previous command");
 				_logged = true;
 				_logged = true;
 			}
 			}
 			
 			
@@ -122,7 +123,7 @@ public final class FloodProtectorAction
 		{
 		{
 			if (_config.LOG_FLOODING && _log.isLoggable(Level.WARNING))
 			if (_config.LOG_FLOODING && _log.isLoggable(Level.WARNING))
 			{
 			{
-				_log.warning(StringUtil.concat(_config.FLOOD_PROTECTOR_TYPE, ": Player [", _player.getName(), "] issued [", String.valueOf(_count), "] extra requests within [~", String.valueOf(_config.FLOOD_PROTECTION_INTERVAL * GameTimeController.MILLIS_IN_TICK), " ms]"));
+				log(" issued ", String.valueOf(_count), " extra requests within ~", String.valueOf(_config.FLOOD_PROTECTION_INTERVAL * GameTimeController.MILLIS_IN_TICK), " ms");
 			}
 			}
 		}
 		}
 		
 		
@@ -138,11 +139,14 @@ public final class FloodProtectorAction
 	 */
 	 */
 	private void kickPlayer()
 	private void kickPlayer()
 	{
 	{
-		_player.logout(false);
+		if (_client.getActiveChar() != null)
+			_client.getActiveChar().logout(false);
+		else
+			_client.closeNow();
 
 
 		if (_log.isLoggable(Level.WARNING))
 		if (_log.isLoggable(Level.WARNING))
 		{
 		{
-			_log.warning(StringUtil.concat(_config.FLOOD_PROTECTOR_TYPE, ": Account [", _player.getAccountName(), "] kicked for flooding [char ", _player.getName(), "]"));
+			log("kicked for flooding");
 		}
 		}
 	}
 	}
 
 
@@ -151,14 +155,19 @@ public final class FloodProtectorAction
 	 */
 	 */
 	private void banAccount()
 	private void banAccount()
 	{
 	{
-		_player.setPunishLevel(L2PcInstance.PunishLevel.ACC, _config.PUNISHMENT_TIME);
-		
-		if (_log.isLoggable(Level.WARNING))
+		if (_client.getActiveChar() != null)
 		{
 		{
-			_log.warning(StringUtil.concat(_config.FLOOD_PROTECTOR_TYPE, ": Account [", _player.getAccountName(), "] banned for flooding [char ", _player.getName(), "] ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + _config.PUNISHMENT_TIME + " mins"));
+			_client.getActiveChar().setPunishLevel(L2PcInstance.PunishLevel.ACC, _config.PUNISHMENT_TIME);
+
+			if (_log.isLoggable(Level.WARNING))
+			{
+				log(" banned for flooding ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + _config.PUNISHMENT_TIME + " mins");
+			}
+
+			_client.getActiveChar().logout();
 		}
 		}
-		
-		_player.logout();
+		else
+			log(" unable to ban account: no active player");
 	}
 	}
 	
 	
 	/**
 	/**
@@ -166,11 +175,52 @@ public final class FloodProtectorAction
 	 */
 	 */
 	private void jailChar()
 	private void jailChar()
 	{
 	{
-		_player.setPunishLevel(L2PcInstance.PunishLevel.JAIL, _config.PUNISHMENT_TIME);
-		
-		if (_log.isLoggable(Level.WARNING))
+		if (_client.getActiveChar() != null)
 		{
 		{
-			_log.warning(StringUtil.concat(_config.FLOOD_PROTECTOR_TYPE, ": Player [", _player.getName(), "] jailed for flooding [char ", _player.getName(), "] ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + _config.PUNISHMENT_TIME + " mins"));
+			_client.getActiveChar().setPunishLevel(L2PcInstance.PunishLevel.JAIL, _config.PUNISHMENT_TIME);
+			
+			if (_log.isLoggable(Level.WARNING))
+			{
+				log(" jailed for flooding ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + _config.PUNISHMENT_TIME + " mins");
+			}
 		}
 		}
+		else
+			log(" unable to jail: no active player");
+	}
+
+	private void log(String... lines)
+	{
+		final StringBuilder output = StringUtil.startAppend(100, _config.FLOOD_PROTECTOR_TYPE, ": ");
+		String address = null;
+		try
+		{
+			if (!_client.isDetached())
+				address = _client.getConnection().getInetAddress().getHostAddress();
+		}
+		catch (Exception e)
+		{
+		}
+
+		switch (_client.getState())
+		{
+			case IN_GAME:
+				if (_client.getActiveChar() != null)
+				{
+					StringUtil.append(output, _client.getActiveChar().getName());
+					StringUtil.append(output, "(", String.valueOf(_client.getActiveChar().getObjectId()),") ");
+				}
+			case AUTHED:
+				if (_client.getAccountName() != null)
+					StringUtil.append(output, _client.getAccountName()," ");
+			case CONNECTED:
+				if (address != null)
+					StringUtil.append(output, address);
+				break;
+			default:
+				throw new IllegalStateException("Missing state on switch");
+		}
+
+		StringUtil.append(output, lines);
+		_log.warning(output.toString());
 	}
 	}
 }
 }

+ 29 - 14
L2_GameServer/java/com/l2jserver/gameserver/util/FloodProtectors.java

@@ -13,7 +13,7 @@
 package com.l2jserver.gameserver.util;
 package com.l2jserver.gameserver.util;
 
 
 import com.l2jserver.Config;
 import com.l2jserver.Config;
-import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.L2GameClient;
 
 
 /**
 /**
  * Collection of flood protectors for single player.
  * Collection of flood protectors for single player.
@@ -71,6 +71,10 @@ public final class FloodProtectors
 	 * Send mail flood protector.
 	 * Send mail flood protector.
 	 */
 	 */
 	private final FloodProtectorAction _sendMail;
 	private final FloodProtectorAction _sendMail;
+	/**
+	 * Character Select protector
+	 */
+	private final FloodProtectorAction _characterSelect;
 
 
 	/**
 	/**
 	 * Creates new instance of FloodProtectors.
 	 * Creates new instance of FloodProtectors.
@@ -78,21 +82,22 @@ public final class FloodProtectors
 	 * @param player
 	 * @param player
 	 *            player for which the collection of flood protectors is being created.
 	 *            player for which the collection of flood protectors is being created.
 	 */
 	 */
-	public FloodProtectors(final L2PcInstance player)
+	public FloodProtectors(final L2GameClient client)
 	{
 	{
 		super();
 		super();
-		_useItem = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_USE_ITEM);
-		_rollDice = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_ROLL_DICE);
-		_firework = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_FIREWORK);
-		_itemPetSummon = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_ITEM_PET_SUMMON);
-		_heroVoice = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_HERO_VOICE);
-		_globalChat = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_GLOBAL_CHAT);
-		_subclass = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_SUBCLASS);
-		_dropItem = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_DROP_ITEM);
-		_serverBypass = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_SERVER_BYPASS);
-		_multiSell = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_MULTISELL);
-		_transaction = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_TRANSACTION);
-		_sendMail = new FloodProtectorAction(player, Config.FLOOD_PROTECTOR_SENDMAIL);
+		_useItem = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_USE_ITEM);
+		_rollDice = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_ROLL_DICE);
+		_firework = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_FIREWORK);
+		_itemPetSummon = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_ITEM_PET_SUMMON);
+		_heroVoice = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_HERO_VOICE);
+		_globalChat = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_GLOBAL_CHAT);
+		_subclass = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_SUBCLASS);
+		_dropItem = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_DROP_ITEM);
+		_serverBypass = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_SERVER_BYPASS);
+		_multiSell = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_MULTISELL);
+		_transaction = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_TRANSACTION);
+		_sendMail = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_SENDMAIL);
+		_characterSelect = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_CHARACTER_SELECT);
 	}
 	}
 	
 	
 	/**
 	/**
@@ -214,4 +219,14 @@ public final class FloodProtectors
 	{
 	{
 		return _sendMail;
 		return _sendMail;
 	}
 	}
+
+	/**
+	 * Returns {@link #_characterSelect}.
+	 * 
+	 * @return {@link #_characterSelect}
+	 */
+	public FloodProtectorAction getCharacterSelect()
+	{
+		return _characterSelect;
+	}
 }
 }

+ 7 - 0
L2_GameServer/java/config/floodprotector.properties

@@ -91,3 +91,10 @@ FloodProtectorSendMailLogFlooding = False
 FloodProtectorSendMailPunishmentLimit = 0
 FloodProtectorSendMailPunishmentLimit = 0
 FloodProtectorSendMailPunishmentType = none
 FloodProtectorSendMailPunishmentType = none
 FloodProtectorSendMailPunishmentTime = 0
 FloodProtectorSendMailPunishmentTime = 0
+
+# CharacterSelect - attempts to load character
+FloodProtectorCharacterSelectInterval = 30
+FloodProtectorCharacterSelectLogFlooding = False
+FloodProtectorCharacterSelectPunishmentLimit = 0
+FloodProtectorCharacterSelectPunishmentType = none
+FloodProtectorCharacterSelectPunishmentTime = 0