Hello everyone! I'm using latest free aCis files. I added Capraso's bots prevention to the server (
But when I'm trying to test it I'm getting this: "WARNING 33 net.sf.l2j.commons.concurrent.ThreadPool Exception in a Runnable execution:java.lang.IllegalArgumentException: bound must be positive" . Bots prevention doesn't work and it also causes to stay some mosters alive with 0 hp (they are not respawning). Any ideas to fix this? Below I'm pasting some *.java
My BotsPreventionManager.java
package net.sf.l2j.gameserver.instancemanager;
import java.io.File;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Future;
import net.sf.l2j.Config;
import net.sf.l2j.L2DatabaseFactory;
import net.sf.l2j.commons.lang.StringUtil;
import net.sf.l2j.commons.concurrent.ThreadPool;
import net.sf.l2j.gameserver.datatables.MapRegionTable;
import net.sf.l2j.gameserver.model.actor.L2Character;
import net.sf.l2j.gameserver.model.actor.instance.L2MonsterInstance;
import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
import net.sf.l2j.gameserver.network.serverpackets.PledgeCrest;
public class BotsPreventionManager
{
private class PlayerData
{
public PlayerData()
{
firstWindow = true;
}
public int mainpattern;
public List<Integer> options = new ArrayList<>();
public boolean firstWindow;
public int patternid;
}
protected Random _randomize;
protected static Map<Integer, Integer> _monsterscounter;
protected static Map<Integer, Future<?>> _beginvalidation;protectedstaticMap<Integer,PlayerData> _validation;protectedstaticMap<Integer,byte[]> _images;protectedint WINDOW_DELAY =3;//delay used to generate new window if previous have been closed.protectedint VALIDATION_TIME =Config.VALIDATION_TIME *1000;publicstaticfinalBotsPreventionManager getInstance(){returnSingletonHolder._instance;}BotsPreventionManager(){
_randomize =newRandom();
_monsterscounter =newHashMap<>();
_beginvalidation =newHashMap<>();
_validation =newHashMap<>();
_images =newHashMap<>();
_beginvalidation =newHashMap<>();
getimages();}publicvoid updatecounter(L2Character player, L2Character monster){if((player instanceof L2PcInstance)&&(monster instanceof L2MonsterInstance)){
L2PcInstance killer =(L2PcInstance) player;if(_validation.get(killer.getObjectId())!=null){return;}int count =1;if(_monsterscounter.get(killer.getObjectId())!=null){
count = _monsterscounter.get(killer.getObjectId())+1;}intnext= _randomize.nextInt(Config.KILLS_COUNTER_RANDOMIZATION);if(Config.KILLS_COUNTER +next< count){
validationtasks(killer);
_monsterscounter.remove(killer.getObjectId());}else{
_monsterscounter.put(killer.getObjectId(), count);}}}privatestaticvoid getimages(){String CRESTS_DIR ="data/html/mods/prevention";finalFile directory =newFile(CRESTS_DIR);
directory.mkdirs();int i =0;for(File file : directory.listFiles()){if(!file.getName().endsWith(".dds"))continue;byte[] data;try(RandomAccessFile f =newRandomAccessFile(file,"r")){
data =newbyte[(int) f.length()];
f.readFully(data);}catch(Exception e){continue;}
_images.put(i, data);
i++;}}publicvoid prevalidationwindow(L2PcInstance player){NpcHtmlMessage html =newNpcHtmlMessage(1);StringBuilder tb =newStringBuilder();StringUtil.append(tb,"<html>");StringUtil.append(tb,"<title>Bots prevention</title>");StringUtil.append(tb,"<body><center><br><br><img src=\"L2UI_CH3.herotower_deco\" width=\"256\" height=\"32\">");StringUtil.append(tb,"<br><br><font color=\"a2a0a2\">if such window appears it means server suspect,<br1>that you may using cheating software.</font>");StringUtil.append(tb,"<br><br><font color=\"b09979\">if given answer results are incorrect or no action is made<br1>server is going to punish character instantly.</font>");StringUtil.append(tb,"<br><br><button value=\"CONTINUE\" action=\"bypass report_continue\" width=\"75\" height=\"21\" back=\"L2UI_CH3.Btn1_normal\" fore=\"L2UI_CH3.Btn1_normal\">");StringUtil.append(tb,"</center></body>");StringUtil.append(tb,"</html>");
html.setHtml(tb.toString());
player.sendPacket(html);}privatestaticvoid validationwindow(L2PcInstance player){PlayerData container = _validation.get(player.getObjectId());NpcHtmlMessage html =newNpcHtmlMessage(1);StringBuilder tb =newStringBuilder();StringUtil.append(tb,"<html>");StringUtil.append(tb,"<title>Bots prevention</title>");StringUtil.append(tb,"<body><center><br><br><img src=\"L2UI_CH3.herotower_deco\" width=\"256\" height=\"32\">");StringUtil.append(tb,"<br><br><font color=\"a2a0a2\">in order to prove you are a human being<br1>you've to</font> <font color=\"b09979\">match colours within generated pattern:</font>");// generated main pattern.StringUtil.append(tb,"<br><br><img src=\"Crest.crest_"+Config.SERVER_ID +"_"+(_validation.get(player.getObjectId()).patternid)+"\" width=\"32\" height=\"32\"></td></tr>");StringUtil.append(tb,"<br><br><font color=b09979>click-on pattern of your choice beneath:</font>");// generate random colours.StringUtil.append(tb,"<table><tr>");for(int i =0; i < container.options.size(); i++){StringUtil.append(tb,"<td><button action=\"bypass -h report_"+ i +"\" width=32 height=32 back=\"Crest.crest_"+Config.SERVER_ID +"_"+(container.options.get(i)+1500)+"\" fore=\"Crest.crest_"+Config.SERVER_ID +"_"+(container.options.get(i)+1500)+"\"></td>");}StringUtil.append(tb,"</tr></table>");StringUtil.append(tb,"</center></body>");StringUtil.append(tb,"</html>");
html.setHtml(tb.toString());
player.sendPacket(html);}publicvoid punishmentnwindow(L2PcInstance player){NpcHtmlMessage html =newNpcHtmlMessage(1);StringBuilder tb =newStringBuilder();StringUtil.append(tb,"<html>");StringUtil.append(tb,"<title>Bots prevention</title>");StringUtil.append(tb,"<body><center><br><br><img src=\"L2UI_CH3.herotower_deco\" width=\"256\" height=\"32\">");StringUtil.append(tb,"<br><br><font color=\"a2a0a2\">if such window appears, it means character haven't<br1>passed through prevention system.");StringUtil.append(tb,"<br><br><font color=\"b09979\">in such case character get moved to nearest town.</font>");StringUtil.append(tb,"</center></body>");StringUtil.append(tb,"</html>");
html.setHtml(tb.toString());
player.sendPacket(html);}publicvoid validationtasks(L2PcInstance player){PlayerData container =newPlayerData();
randomizeimages(container, player);for(int i =0; i < container.options.size(); i++){PledgeCrest packet =newPledgeCrest((container.options.get(i)+1500), _images.get(container.options.get(i)));
player.sendPacket(packet);}PledgeCrest packet =newPledgeCrest(container.patternid, _images.get(container.options.get(container.mainpattern)));
player.sendPacket(packet);
_validation.put(player.getObjectId(), container);Future<?> newTask = ThreadPool.schedule(new ReportCheckTask(player), VALIDATION_TIME);
ThreadPool.schedule(new countdown(player, VALIDATION_TIME / 1000), 0);
_beginvalidation.put(player.getObjectId(), newTask);
}
protected void randomizeimages(PlayerData container,L2PcInstance player)
{
int buttonscount = 4;
int imagescount = _images.size();
for (int i = 0; i < buttonscount; i++)
{
int next = _randomize.nextInt(imagescount);
while (container.options.indexOf(next) > -1)
{
next = _randomize.nextInt(imagescount);
}
container.options.add(next);
}
int mainIndex = _randomize.nextInt(buttonscount);
container.mainpattern = mainIndex;
Calendar token = Calendar.getInstance();
String uniquetoken = Integer.toString(token.get(Calendar.DAY_OF_MONTH))+Integer.toString(token.get(Calendar.HOUR_OF_DAY))+Integer.toString(token.get(Calendar.MINUTE))+Integer.toString(token.get(Calendar.SECOND))+Integer.toString(token.get(Calendar.MILLISECOND)/100);
container.patternid = Integer.parseInt(uniquetoken);
}
protected void banpunishment(L2PcInstance player)
{
_validation.remove(player.getObjectId());
_beginvalidation.get(player.getObjectId()).cancel(true);
_beginvalidation.remove(player.getObjectId());
switch (Config.PUNISHMENT)
{
// 0 = move character to the closest village.
// 1 = kick characters from the server.
// 2 = put character to jail.
// 3 = ban character from the server.
case 0:
player.stopMove(null);
player.teleToLocation(MapRegionTable.TeleportWhereType.TOWN);
punishmentnwindow(player);
break;
case 1:
if (player.isOnline())
{
player.logout(true);
}
break;
case 2:
jailpunishment(player, Config.PUNISHMENT_TIME * 60);
break;
case 3:
//player.setAccessLevel(-100);
changeaccesslevel(player, -100);
break;
}
player.sendMessage("Unfortunately, colours doesn't match.");
}
private static void changeaccesslevel(L2PcInstance targetPlayer, int lvl)
{
if (targetPlayer.isOnline())
{
targetPlayer.setAccessLevel(lvl);
targetPlayer.logout();
}
else
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
PreparedStatement statement = con.prepareStatement("UPDATE characters SET accesslevel=? WHERE obj_id=?");
statement.setInt(1, lvl);
statement.setInt(2, targetPlayer.getObjectId());
statement.execute();
statement.close();
}
catch (SQLException se)
{
if (Config.DEBUG)
se.printStackTrace();
}
}
}
private static void jailpunishment(L2PcInstance activeChar, int delay)
{
if (activeChar.isOnline())
{
activeChar.setPunishLevel(L2PcInstance.PunishLevel.JAIL, Config.PUNISHMENT_TIME);
}
else
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
PreparedStatement statement = con.prepareStatement("UPDATE characters SET x=?, y=?, z=?, punish_level=?, punish_timer=? WHERE obj_id=?");
statement.setInt(1, -114356);
statement.setInt(2, -249645);
statement.setInt(3, -2984);
statement.setInt(4, L2PcInstance.PunishLevel.JAIL.value());
statement.setLong(5, (delay > 0 ? delay * Config.PUNISHMENT_TIME * 100 : 0));
statement.setInt(6, activeChar.getObjectId());
statement.execute();
statement.close();
}
catch (SQLException se)
{
activeChar.sendMessage("SQLException while jailing player");
if (Config.DEBUG)
se.printStackTrace();
}
}
}
public void AnalyseBypass(String command, L2PcInstance player)
{
if (!_validation.containsKey(player.getObjectId()))
return;
String params = command.substring(command.indexOf("_") + 1);
if (params.startsWith("continue"))
{
validationwindow(player);
_validation.get(player.getObjectId()).firstWindow = false;
return;
}
int choosenoption = -1;
if (tryParseInt(params))
{
choosenoption = Integer.parseInt(params);
}
if (choosenoption > -1)
{
PlayerData playerData = _validation.get(player.getObjectId());
if (choosenoption != playerData.mainpattern)
{
banpunishment(player);
}
else
{
player.sendMessage("Congratulations, colours match!");
_validation.remove(player.getObjectId());
_beginvalidation.get(player.getObjectId()).cancel(true);
_beginvalidation.remove(player.getObjectId());
}
}
}
protected class countdown implements Runnable
{
private final L2PcInstance _player;
private int _time;
public countdown(L2PcInstance player, int time)
{
_time = time;
_player = player;
}
@Override
public void run()
{
if (_player.isOnline())
{
if (_validation.containsKey(_player.getObjectId()) && _validation.get(_player.getObjectId()).firstWindow)
{
if (_time % WINDOW_DELAY == 0)
{
prevalidationwindow(_player);
}
}
switch (_time)
{
case 300:
case 240:
case 180:
case 120:
case 60:
_player.sendMessage(_time / 60 + " minute(s) to match colors.");
break;
case 30:
case 10:
case 5:
case 4:
case 3:
case 2:
case 1:
_player.sendMessage(_time + " second(s) to match colors!");
break;
}
if (_time > 1 && _validation.containsKey(_player.getObjectId()))
{
ThreadPool.schedule(new countdown(_player, _time - 1), 1000);
}
}
}
}
protected boolean tryParseInt(String value)
{
try
{
Integer.parseInt(value);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
public void CaptchaSuccessfull(L2PcInstance player)
{
if (_validation.get(player.getObjectId()) != null)
{
_validation.remove(player.getObjectId());
}
}
public Boolean IsAlredyInReportMode(L2PcInstance player)
{
if (_validation.get(player.getObjectId()) != null)
{
return true;
}
return false;
}
private class ReportCheckTask implements Runnable
{
private final L2PcInstance _player;
public ReportCheckTask(L2PcInstance player)
{
_player = player;
}
@Override
public void run()
{
if (_validation.get(_player.getObjectId()) != null)
{
banpunishment(_player);
}
}
}
private static class SingletonHolder
{
protected static final BotsPreventionManager _instance = new BotsPreventionManager();
}
}
My ThreadPool.java
/*
* 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 net.sf.l2j.commons.concurrent;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import net.sf.l2j.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools :
* </p>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
* </ul>
*/
public final class ThreadPool
{
protected static final Logger LOG = Logger.getLogger(ThreadPool.class.getName());
private static final long MAX_DELAY = TimeUnit.NANOSECONDS.toMillis(Long.MAX_VALUE - System.nanoTime()) / 2;
private static int _threadPoolRandomizer;
protected static ScheduledThreadPoolExecutor[] _scheduledPools;
protected static ThreadPoolExecutor[] _instantPools;
/**
* Init the different pools, based on Config. It is launched only once, on Gameserver instance.
*/
public static void init()
{
// Feed scheduled pool.
int poolCount = Config.SCHEDULED_THREAD_POOL_COUNT;
if (poolCount == -1)
poolCount = Runtime.getRuntime().availableProcessors();
_scheduledPools = new ScheduledThreadPoolExecutor[poolCount];
for (int i = 0; i < poolCount; i++)
_scheduledPools[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
// Feed instant pool.
poolCount = Config.INSTANT_THREAD_POOL_COUNT;
if (poolCount == -1)
poolCount = Runtime.getRuntime().availableProcessors();
_instantPools = new ThreadPoolExecutor[poolCount];
for (int i = 0; i < poolCount; i++)
_instantPools[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : _scheduledPools)
threadPool.prestartAllCoreThreads();
for (ThreadPoolExecutor threadPool : _instantPools)
threadPool.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(new Runnable()
{
@Override
public void run()
{
for (ScheduledThreadPoolExecutor threadPool : _scheduledPools)
threadPool.purge();
for (ThreadPoolExecutor threadPool : _instantPools)
threadPool.purge();
}
}, 600000, 600000);
LOG.info("ThreadPool: Initialized " + getPoolSize(_scheduledPools) + "/" + getMaximumPoolSize(_scheduledPools) + " scheduled, " + getPoolSize(_instantPools) + "/" + getMaximumPoolSize(_instantPools) + " instant thread(s).");
}
/**
* Schedules a one-shot action that becomes enabled after a delay. The pool is chosen based on pools activity.
* @param r : the task to execute.
* @param delay : the time from now to delay execution.
* @return a ScheduledFuture representing pending completion of the task and whose get() method will return null upon completion.
*/
public static ScheduledFuture<?> schedule(Runnable r,long delay){try{return getPool(_scheduledPools).schedule(newTaskWrapper(r), validate(delay),TimeUnit.MILLISECONDS);}catch(Exception e){returnnull;}}/**
* Schedules a periodic action that becomes enabled after a delay. The pool is chosen based on pools activity.
* @param r : the task to execute.
* @param delay : the time from now to delay execution.
* @param period : the period between successive executions.
* @return a ScheduledFuture representing pending completion of the task and whose get() method will throw an exception upon cancellation.
*/publicstaticScheduledFuture<?> scheduleAtFixedRate(Runnable r, long delay, long period)
{
try
{
return getPool(_scheduledPools).scheduleAtFixedRate(new TaskWrapper(r), validate(delay), validate(period), TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
}
/**
* Executes the given task sometime in the future.
* @param r : the task to execute.
*/
public static void execute(Runnable r)
{
try
{
getPool(_instantPools).execute(new TaskWrapper(r));
}
catch (Exception e)
{
}
}
/**
* Retrieve stats of current running thread pools.
*/
public static void getStats()
{
for (int i = 0; i < _scheduledPools.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = _scheduledPools[i];
LOG.info("=================================================");
LOG.info("Scheduled pool #" + i + ":");
LOG.info("\tgetActiveCount: ...... " + threadPool.getActiveCount());
LOG.info("\tgetCorePoolSize: ..... " + threadPool.getCorePoolSize());
LOG.info("\tgetPoolSize: ......... " + threadPool.getPoolSize());
LOG.info("\tgetLargestPoolSize: .. " + threadPool.getLargestPoolSize());
LOG.info("\tgetMaximumPoolSize: .. " + threadPool.getMaximumPoolSize());
LOG.info("\tgetCompletedTaskCount: " + threadPool.getCompletedTaskCount());
LOG.info("\tgetQueuedTaskCount: .. " + threadPool.getQueue().size());
LOG.info("\tgetTaskCount: ........ " + threadPool.getTaskCount());
}
for (int i = 0; i < _instantPools.length; i++)
{
final ThreadPoolExecutor threadPool = _instantPools[i];
LOG.info("=================================================");
LOG.info("Instant pool #" + i + ":");
LOG.info("\tgetActiveCount: ...... " + threadPool.getActiveCount());
LOG.info("\tgetCorePoolSize: ..... " + threadPool.getCorePoolSize());
LOG.info("\tgetPoolSize: ......... " + threadPool.getPoolSize());
LOG.info("\tgetLargestPoolSize: .. " + threadPool.getLargestPoolSize());
LOG.info("\tgetMaximumPoolSize: .. " + threadPool.getMaximumPoolSize());
LOG.info("\tgetCompletedTaskCount: " + threadPool.getCompletedTaskCount());
LOG.info("\tgetQueuedTaskCount: .. " + threadPool.getQueue().size());
LOG.info("\tgetTaskCount: ........ " + threadPool.getTaskCount());
}
}
/**
* Shutdown thread pooling system correctly. Send different informations.
*/
public static void shutdown()
{
try
{
System.out.println("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : _scheduledPools)
threadPool.shutdownNow();
for (ThreadPoolExecutor threadPool : _instantPools)
threadPool.shutdownNow();
}
catch (Throwable t)
{
t.printStackTrace();
}
}
/**
* @param <T> : The pool type.
* @param threadPools : The pool array to check.
* @return the less fed pool.
*/
private static <T> T getPool(T[] threadPools)
{
return threadPools[_threadPoolRandomizer++ % threadPools.length];
}
/**
* @param delay : The delay to validate.
* @return a secured value, from 0 to MAX_DELAY.
*/
private static long validate(long delay)
{
return Math.max(0, Math.min(MAX_DELAY, delay));
}
/**
* @param threadPools : The pool array to check.
* @return the overall actual pools size.
*/
private static long getPoolSize(ThreadPoolExecutor[] threadPools)
{
long result = 0;
for (ThreadPoolExecutor threadPool : threadPools)
result += threadPool.getPoolSize();
return result;
}
/**
* @param threadPools : The pool array to check.
* @return the overall maximum pools size.
*/
private static long getMaximumPoolSize(ThreadPoolExecutor[] threadPools)
{
long result = 0;
for (ThreadPoolExecutor threadPool : threadPools)
result += threadPool.getMaximumPoolSize();
return result;
}
public static final class TaskWrapper implements Runnable
{
private final Runnable _runnable;
public TaskWrapper(Runnable runnable)
{
_runnable = runnable;
}
@Override
public void run()
{
try
{
_runnable.run();
}
catch (RuntimeException e)
{
LOG.warning("Exception in a Runnable execution:" + e);
}
}
}
}
DISCORD :
utchiha_market
telegram :
https://t.me/utchiha_market
SELLIX STORE :
https://utchihamkt.mysellix.io/
Join our server for more products :
https://discord.gg/hood-services
https://campsite.bio/utchihaamkt
Question
devil12pl
Hello everyone! I'm using latest free aCis files. I added Capraso's bots prevention to the server (
But when I'm trying to test it I'm getting this: "WARNING 33 net.sf.l2j.commons.concurrent.ThreadPool Exception in a Runnable execution:java.lang.IllegalArgumentException: bound must be positive" . Bots prevention doesn't work and it also causes to stay some mosters alive with 0 hp (they are not respawning). Any ideas to fix this? Below I'm pasting some *.java
My BotsPreventionManager.java
My ThreadPool.java
Link to comment
Share on other sites
3 answers to this question
Recommended Posts