Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: /trunk/aCis_gameserver/config/server.properties
- ===================================================================
- --- /trunk/aCis_gameserver/config/server.properties (revision 427)
- +++ /trunk/aCis_gameserver/config/server.properties (revision 428)
- @@ -286,5 +286,5 @@
- # =================================================================
- # Misc
- # =================================================================
- # Basic protection against L2Walker.
- L2WalkerProtection = False
- # Zone setting.
- # 0 = Peace All the Time
- # 1 = PVP During Siege for siege participants
- # 2 = PVP All the Time
- ZoneTown = 0
- # Show "data/html/servnews.htm" when a character logins from lvl 5.
- ServerNews = 5
- # Disable tutorial on new player game entrance. Default: False.
- DisableTutorial = False
- +# =================================================================
- +# Misc
- +# =================================================================
- +
- +# Bots prevention system.
- +EnableBotsPrevention = False
- +# How many monsters have to be killed to run validation task?
- +KillsCounter = 60
- +# Specify range of randomly taken values summed with main counter.
- +KillsCounterRandomization = 50
- +# How long validation window awaits an answer? (in seconds)
- +ValidationTime = 60
- +# Punishments:
- +# 0 = move character to the closest village.
- +# 1 = kick characters from the server.
- +# 2 = put character to jail.
- +# 3 = ban character from the server.
- +Punishment = 0
- +# How long character were suppose to stay in jail? (in minutes)
- +PunishmentTime = 60
- +
- +# Basic protection against L2Walker.
- +L2WalkerProtection = False
- +
- Index: trunk/aCis_gameserver/java/net/sf/l2j/Config.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/Config.java (rιvision 427)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/Config.java (rιvision 428)
- @@ -653,5 +653,5 @@
- /** Misc */
- + public static boolean BOTS_PREVENTION;
- + public static int KILLS_COUNTER;
- + public static int KILLS_COUNTER_RANDOMIZATION;
- + public static int VALIDATION_TIME;
- + public static int PUNISHMENT;
- + public static int PUNISHMENT_TIME;
- @@ -1264 +1264 @@
- L2WALKER_PROTECTION = server.getProperty("L2WalkerProtection", false);
- + BOTS_PREVENTION = server.getProperty("EnableBotsPrevention", false);
- + KILLS_COUNTER = server.getProperty("KillsCounter", 60);
- + KILLS_COUNTER_RANDOMIZATION = server.getProperty("KillsCounterRandomization", 50);
- + VALIDATION_TIME = server.getProperty("ValidationTime", 60);
- + PUNISHMENT = server.getProperty("Punishment", 0);
- + PUNISHMENT_TIME = server.getProperty("PunishmentTime", 60);
- Index: trunk/aCis_gameserver/java/net/sf/l2j/gameserver/instancemanager/BotsPreventionManager.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/gameserver/instancemanager/BotsPreventionManager.java (revision 0)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/gameserver/instancemanager/BotsPreventionManager.java (revision 1)
- @@ -0 +0 @@
- +package net.sf.l2j.gameserver.instancemanager;
- +
- +import java.awt.image.BufferedImage;
- +import java.sql.Connection;
- +import java.sql.PreparedStatement;
- +import java.sql.SQLException;
- +import java.util.HashMap;
- +import java.util.Map;
- +import java.util.Random;
- +import java.util.concurrent.ConcurrentHashMap;
- +import java.util.concurrent.Future;
- +
- +import net.sf.l2j.commons.concurrent.ThreadPool;
- +import net.sf.l2j.commons.lang.StringUtil;
- +
- +import net.sf.l2j.Config;
- +import net.sf.l2j.L2DatabaseFactory;
- +import net.sf.l2j.gameserver.datatables.MapRegionTable;
- +import net.sf.l2j.gameserver.features.Captcha;
- +import net.sf.l2j.gameserver.features.DDSConverter;
- +import net.sf.l2j.gameserver.features.ImageData;
- +import net.sf.l2j.gameserver.model.actor.Character;
- +import net.sf.l2j.gameserver.model.actor.instance.Monster;
- +import net.sf.l2j.gameserver.model.actor.instance.Player;
- +import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
- +import net.sf.l2j.gameserver.network.serverpackets.PledgeCrest;
- +
- +public class BotsPreventionManager
- +{
- + public class PlayerData
- + {
- + public PlayerData()
- + {
- + firstWindow = true;
- + }
- +
- + public boolean firstWindow;
- + public BufferedImage image;
- + public String captchaText = "";
- + public int captchaID = 0;
- + }
- +
- + protected Random _randomize;
- + protected static Map<Integer, ImageData> _imageMap;
- + protected static Map<Integer, Integer> _monsterscounter;
- + protected static Map<Integer, Future<?>> _beginvalidation;
- + protected static Map<Integer, PlayerData> _validation;
- + protected int WINDOW_DELAY = 3; // delay used to generate new window if previous have been closed.
- + protected int VALIDATION_TIME = Config.VALIDATION_TIME * 1000;
- + private int USEDID = 0;
- +
- + public static final BotsPreventionManager getInstance()
- + {
- + return SingletonHolder._instance;
- + }
- +
- + BotsPreventionManager()
- + {
- + _randomize = new Random();
- + _monsterscounter = new HashMap<>();
- + _beginvalidation = new HashMap<>();
- + _validation = new HashMap<>();
- + _beginvalidation = new HashMap<>();
- + _imageMap = new ConcurrentHashMap<>();
- + _imageMap = Captcha.getInstance().createImageList();
- + }
- +
- + public void updatecounter(Character player, Character monster)
- + {
- + if ((player instanceof Player) && (monster instanceof Monster))
- + {
- + Player killer = (Player) player;
- +
- + if (_validation.get(killer.getObjectId()) != null)
- + {
- + return;
- + }
- +
- + int count = 1;
- + if (_monsterscounter.get(killer.getObjectId()) != null)
- + {
- + count = _monsterscounter.get(killer.getObjectId()) + 1;
- + }
- +
- + int next = _randomize.nextInt(Config.KILLS_COUNTER_RANDOMIZATION);
- + if (Config.KILLS_COUNTER + next < count)
- + {
- + validationtasks(killer);
- + _monsterscounter.remove(killer.getObjectId());
- + }
- + else
- + {
- + _monsterscounter.put(killer.getObjectId(), count);
- + }
- + }
- + }
- +
- + public void prevalidationwindow(Player player)
- + {
- + NpcHtmlMessage html = new NpcHtmlMessage(1);
- + StringBuilder tb = new StringBuilder();
- + 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);
- + }
- +
- + private static void validationwindow(Player player)
- + {
- + PlayerData container = _validation.get(player.getObjectId());
- + NpcHtmlMessage html = new NpcHtmlMessage(1);
- +
- + StringBuilder tb = new StringBuilder();
- + 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\">enter the code from picture:</font>");
- +
- + // generated main pattern.
- + StringUtil.append(tb, "<br><br><img src=\"Crest.crest_" + Config.SERVER_ID + "_" + (container.captchaID) + "\" width=256 height=64></td></tr>");
- + StringUtil.append(tb, "<br>");
- + StringUtil.append(tb, "<br><br><edit var=\"answer\" width=110>");
- + StringUtil.append(tb, "<br><button value=\"Confirm\" action=\"bypass -h report_ $answer\" width=\"75\" height=\"21\" back=\"L2UI_CH3.Btn1_normal\" fore=\"L2UI_CH3.Btn1_normal\"><br/>");
- + StringUtil.append(tb, "</center></body>");
- + StringUtil.append(tb, "</html>");
- +
- + html.setHtml(tb.toString());
- + player.sendPacket(html);
- + }
- +
- + public void punishmentnwindow(Player player)
- + {
- + NpcHtmlMessage html = new NpcHtmlMessage(1);
- + StringBuilder tb = new StringBuilder();
- + 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);
- + }
- +
- + public void validationtasks(Player player)
- + {
- + PlayerData container = new PlayerData();
- + // Captcha.getInstance().generateCaptcha(container, player);
- + container.image = _imageMap.get(getInstance().USEDID).image;
- + container.captchaID = _imageMap.get(getInstance().USEDID).captchaID;
- + container.captchaText = _imageMap.get(getInstance().USEDID).captchaText;
- + PledgeCrest packet = new PledgeCrest(container.captchaID, DDSConverter.convertToDDS(container.image).array());
- + player.sendPacket(packet);
- + getInstance().USEDID++;
- +
- + if (getInstance().USEDID == 998)
- + {
- + getInstance().USEDID = 0;
- + ThreadPool.schedule(() -> {
- + _imageMap = Captcha.getInstance().createImageList();
- + }, 100);
- + }
- + _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 banpunishment(Player 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.TeleportType.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, code doesn't match.");
- + }
- +
- + private static void changeaccesslevel(Player 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(Player activeChar, int delay)
- + {
- + if (activeChar.isOnline())
- + {
- + activeChar.setPunishLevel(Player.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, Player.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, Player 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;
- + }
- +
- + PlayerData playerData = _validation.get(player.getObjectId());
- + if (!params.trim().equalsIgnoreCase(playerData.captchaText))
- + {
- + banpunishment(player);
- + }
- + else
- + {
- + player.sendMessage("Congratulations, code match!");
- + _validation.remove(player.getObjectId());
- + _beginvalidation.get(player.getObjectId()).cancel(true);
- + _beginvalidation.remove(player.getObjectId());
- + }
- +
- + }
- +
- + protected class countdown implements Runnable
- + {
- + private final Player _player;
- + private int _time;
- +
- + public countdown(Player 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 enter the code.");
- + break;
- + case 30:
- + case 10:
- + case 5:
- + case 4:
- + case 3:
- + case 2:
- + case 1:
- + _player.sendMessage(_time + " second(s) to enter the code!");
- + 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(Player player)
- + {
- + if (_validation.get(player.getObjectId()) != null)
- + {
- + _validation.remove(player.getObjectId());
- + }
- + }
- +
- + public Boolean IsAlredyInReportMode(Player player)
- + {
- + if (_validation.get(player.getObjectId()) != null)
- + {
- + return true;
- + }
- + return false;
- + }
- +
- + private class ReportCheckTask implements Runnable
- + {
- + private final Player _player;
- +
- + public ReportCheckTask(Player 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();
- + }
- +}
- Index: trunk/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/Character.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/Character.java (revision 427)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/Character.java (revision 428)
- @@ -41 +42 @@
- -import net.sf.l2j.gameserver.handler.SkillHandler;
- +import net.sf.l2j.gameserver.handler.SkillHandler;
- +import net.sf.l2j.gameserver.instancemanager.BotsPreventionManager;
- @@ -1613 +1613 @@
- calculateRewards(killer);
- + if (Config.BOTS_PREVENTION)
- + {
- + BotsPreventionManager.getInstance().updatecounter(killer,this);
- + }
- +
- Index: trunk/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/RequestBypassToServer.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/RequestBypassToServer.java (revision 427)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/RequestBypassToServer.java (revision 428)
- @@ -24 +24 @@
- -import net.sf.l2j.gameserver.handler.IAdminCommandHandler;
- +import net.sf.l2j.gameserver.handler.IAdminCommandHandler;
- +import net.sf.l2j.gameserver.instancemanager.BotsPreventionManager;
- @@ -166 +166 @@
- - else if (_command.startsWith("arenachange")) // change
- - {
- - final boolean isManager = activeChar.getCurrentFolkNPC() instanceof L2OlympiadManagerInstance;
- - if (!isManager)
- - {
- - // Without npc, command can be used only in observer mode on arena
- - if (!activeChar.inObserverMode() || activeChar.isInOlympiadMode() || activeChar.getOlympiadGameId() < 0)
- - return;
- - }
- -
- - if (OlympiadManager.getInstance().isRegisteredInComp(activeChar))
- - {
- - activeChar.sendPacket(SystemMessageId.WHILE_YOU_ARE_ON_THE_WAITING_LIST_YOU_ARE_NOT_ALLOWED_TO_WATCH_THE_GAME);
- - return;
- - }
- -
- - final int arenaId = Integer.parseInt(_command.substring(12).trim());
- - activeChar.enterOlympiadObserverMode(arenaId);
- - }
- + else if (_command.startsWith("arenachange")) // change
- + {
- + final boolean isManager = activeChar.getCurrentFolkNPC() instanceof OlympiadManagerNpc;
- + if (!isManager)
- + {
- + // Without npc, command can be used only in observer mode on arena
- + if (!activeChar.isInObserverMode() || activeChar.isInOlympiadMode() || activeChar.getOlympiadGameId() < 0)
- + return;
- + }
- +
- + if (OlympiadManager.getInstance().isRegisteredInComp(activeChar))
- + {
- + activeChar.sendPacket(SystemMessageId.WHILE_YOU_ARE_ON_THE_WAITING_LIST_YOU_ARE_NOT_ALLOWED_TO_WATCH_THE_GAME);
- + return;
- + }
- +
- + final int arenaId = Integer.parseInt(_command.substring(12).trim());
- + activeChar.enterOlympiadObserverMode(arenaId);
- + }
- + else if (_command.startsWith("report"))
- + {
- + BotsPreventionManager.getInstance().AnalyseBypass(_command,activeChar);
- + }
- Index: trunk/aCis_gameserver/java/net/sf/l2j/gameserver/network/serverpackets/PledgeCrest.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/gameserver/network/serverpackets/PledgeCrest.java (revision 427)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/gameserver/network/serverpackets/PledgeCrest.java (revision 428)
- @@ -29 +29 @@
- - }
- -
- - @Override
- - protected final void writeImpl()
- + }
- +
- + public PledgeCrest(int crestId, byte[] data)
- + {
- + _crestId = crestId;
- + _data = data;
- + }
- +
- + @Override
- + protected final void writeImpl()
- +
- Index: trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/DDSConverter.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/DDSConverter.java (revision 427)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/DDSConverter.java (revision 428)
- +package net.sf.l2j.gameserver.features;
- +
- +import java.awt.image.BufferedImage;
- +import java.io.File;
- +import java.io.IOException;
- +import java.nio.ByteBuffer;
- +import java.nio.ByteOrder;
- +import java.util.logging.Logger;
- +
- +import javax.imageio.ImageIO;
- +
- +public class DDSConverter
- +{
- + protected static final Logger LOG = Logger.getLogger(DDSConverter.class.getName());
- +
- + protected static class Color
- + {
- +
- + @Override
- + public boolean equals(Object obj)
- + {
- + if (this == obj)
- + {
- + return true;
- + }
- + if ((obj == null) || (getClass() != obj.getClass()))
- + {
- + return false;
- + }
- + Color color = (Color) obj;
- + if (b != color.b)
- + {
- + return false;
- + }
- + if (g != color.g)
- + {
- + return false;
- + }
- + return r == color.r;
- + }
- +
- + @Override
- + public int hashCode()
- + {
- + int i = r;
- + i = (29 * i) + g;
- + i = (29 * i) + b;
- + return i;
- + }
- +
- + protected int r;
- + protected int g;
- + protected int b;
- +
- + public Color()
- + {
- + r = g = b = 0;
- + }
- +
- + public Color(int i, int j, int k)
- + {
- + r = i;
- + g = j;
- + b = k;
- + }
- + }
- +
- + public static ByteBuffer convertToDDS(BufferedImage bufferedimage)
- + {
- + if (bufferedimage == null)
- + {
- + return null;
- + }
- + if (bufferedimage.getColorModel().hasAlpha())
- + {
- + return convertToDxt3(bufferedimage);
- + }
- + return convertToDxt1NoTransparency(bufferedimage);
- + }
- +
- + public static ByteBuffer convertToDDS(File file)
- + {
- + if (file == null)
- + {
- + String s = "nullValue.FileIsNull";
- + LOG.severe(s + " " + new IllegalArgumentException(s));
- + new IllegalArgumentException(s);
- + return null;
- + }
- + if (!file.exists() || !file.canRead())
- + {
- + String s1 = "DDSConverter.NoFileOrNoPermission";
- + LOG.severe(s1 + " " + new IllegalArgumentException(s1));
- + new IllegalArgumentException(s1);
- + return null;
- + }
- + BufferedImage bufferedimage = null;
- + try
- + {
- + bufferedimage = ImageIO.read(file);
- + }
- + catch (IOException e)
- + {
- + e.printStackTrace();
- + //LOG.error("Error while reading Image that needs to be DDSConverted", e);
- + }
- + if (bufferedimage == null)
- + {
- + return null;
- + }
- + if (bufferedimage.getColorModel().hasAlpha())
- + {
- + return convertToDxt3(bufferedimage);
- + }
- + return convertToDxt1NoTransparency(bufferedimage);
- + }
- +
- + public static ByteBuffer convertToDxt1NoTransparency(BufferedImage bufferedimage)
- + {
- + if (bufferedimage == null)
- + {
- + return null;
- + }
- + int ai[] = new int[16];
- + int i = 128 + ((bufferedimage.getWidth() * bufferedimage.getHeight()) / 2);
- + ByteBuffer bytebuffer = ByteBuffer.allocate(i);
- + bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
- + buildHeaderDxt1(bytebuffer, bufferedimage.getWidth(), bufferedimage.getHeight());
- + int j = bufferedimage.getWidth() / 4;
- + int k = bufferedimage.getHeight() / 4;
- + for (int l = 0; l < k; l++)
- + {
- + for (int i1 = 0; i1 < j; i1++)
- + {
- + BufferedImage bufferedimage1 = bufferedimage.getSubimage(i1 * 4, l * 4, 4, 4);
- + bufferedimage1.getRGB(0, 0, 4, 4, ai, 0, 4);
- + Color acolor[] = getColors888(ai);
- + for (int j1 = 0; j1 < ai.length; j1++)
- + {
- + ai[j1] = getPixel565(acolor[j1]);
- + acolor[j1] = getColor565(ai[j1]);
- + }
- +
- + int ai1[] = determineExtremeColors(acolor);
- + if (ai[ai1[0]] < ai[ai1[1]])
- + {
- + int k1 = ai1[0];
- + ai1[0] = ai1[1];
- + ai1[1] = k1;
- + }
- + bytebuffer.putShort((short) ai[ai1[0]]);
- + bytebuffer.putShort((short) ai[ai1[1]]);
- + long l1 = computeBitMask(acolor, ai1);
- + bytebuffer.putInt((int) l1);
- + }
- +
- + }
- +
- + return bytebuffer;
- + }
- +
- + public static ByteBuffer convertToDxt3(BufferedImage bufferedimage)
- + {
- + if (bufferedimage == null)
- + {
- + return null;
- + }
- + if (!bufferedimage.getColorModel().hasAlpha())
- + {
- + return convertToDxt1NoTransparency(bufferedimage);
- + }
- + int ai[] = new int[16];
- + int i = 128 + (bufferedimage.getWidth() * bufferedimage.getHeight());
- + ByteBuffer bytebuffer = ByteBuffer.allocate(i);
- + bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
- + buildHeaderDxt3(bytebuffer, bufferedimage.getWidth(), bufferedimage.getHeight());
- + int j = bufferedimage.getWidth() / 4;
- + int k = bufferedimage.getHeight() / 4;
- + for (int l = 0; l < k; l++)
- + {
- + for (int i1 = 0; i1 < j; i1++)
- + {
- + BufferedImage bufferedimage1 = bufferedimage.getSubimage(i1 * 4, l * 4, 4, 4);
- + bufferedimage1.getRGB(0, 0, 4, 4, ai, 0, 4);
- + Color acolor[] = getColors888(ai);
- + for (int j1 = 0; j1 < ai.length; j1 += 2)
- + {
- + bytebuffer.put((byte) ((ai[j1] >>> 28) | (ai[j1 + 1] >>> 24)));
- + }
- +
- + for (int k1 = 0; k1 < ai.length; k1++)
- + {
- + ai[k1] = getPixel565(acolor[k1]);
- + acolor[k1] = getColor565(ai[k1]);
- + }
- +
- + int ai1[] = determineExtremeColors(acolor);
- + if (ai[ai1[0]] < ai[ai1[1]])
- + {
- + int l1 = ai1[0];
- + ai1[0] = ai1[1];
- + ai1[1] = l1;
- + }
- + bytebuffer.putShort((short) ai[ai1[0]]);
- + bytebuffer.putShort((short) ai[ai1[1]]);
- + long l2 = computeBitMask(acolor, ai1);
- + bytebuffer.putInt((int) l2);
- + }
- +
- + }
- +
- + return bytebuffer;
- + }
- +
- + protected static void buildHeaderDxt1(ByteBuffer bytebuffer, int i, int j)
- + {
- + bytebuffer.rewind();
- + bytebuffer.put((byte) 68);
- + bytebuffer.put((byte) 68);
- + bytebuffer.put((byte) 83);
- + bytebuffer.put((byte) 32);
- + bytebuffer.putInt(124);
- + int k = 0xa1007;
- + bytebuffer.putInt(k);
- + bytebuffer.putInt(j);
- + bytebuffer.putInt(i);
- + bytebuffer.putInt((i * j) / 2);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.position(bytebuffer.position() + 44);
- + bytebuffer.putInt(32);
- + bytebuffer.putInt(4);
- + bytebuffer.put((byte) 68);
- + bytebuffer.put((byte) 88);
- + bytebuffer.put((byte) 84);
- + bytebuffer.put((byte) 49);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(4096);
- + bytebuffer.putInt(0);
- + bytebuffer.position(bytebuffer.position() + 12);
- + }
- +
- + protected static void buildHeaderDxt3(ByteBuffer bytebuffer, int i, int j)
- + {
- + bytebuffer.rewind();
- + bytebuffer.put((byte) 68);
- + bytebuffer.put((byte) 68);
- + bytebuffer.put((byte) 83);
- + bytebuffer.put((byte) 32);
- + bytebuffer.putInt(124);
- + int k = 0xa1007;
- + bytebuffer.putInt(k);
- + bytebuffer.putInt(j);
- + bytebuffer.putInt(i);
- + bytebuffer.putInt(i * j);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.position(bytebuffer.position() + 44);
- + bytebuffer.putInt(32);
- + bytebuffer.putInt(4);
- + bytebuffer.put((byte) 68);
- + bytebuffer.put((byte) 88);
- + bytebuffer.put((byte) 84);
- + bytebuffer.put((byte) 51);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(0);
- + bytebuffer.putInt(4096);
- + bytebuffer.putInt(0);
- + bytebuffer.position(bytebuffer.position() + 12);
- + }
- +
- + protected static int[] determineExtremeColors(Color acolor[])
- + {
- + int i = 0x80000000;
- + int ai[] = new int[2];
- + for (int j = 0; j < (acolor.length - 1); j++)
- + {
- + for (int k = j + 1; k < acolor.length; k++)
- + {
- + int l = distance(acolor[j], acolor[k]);
- + if (l > i)
- + {
- + i = l;
- + ai[0] = j;
- + ai[1] = k;
- + }
- + }
- +
- + }
- +
- + return ai;
- + }
- +
- + protected static long computeBitMask(Color acolor[], int ai[])
- + {
- + Color acolor1[] =
- + {
- + null,
- + null,
- + new Color(),
- + new Color()
- + };
- + acolor1[0] = acolor[ai[0]];
- + acolor1[1] = acolor[ai[1]];
- + if (acolor1[0].equals(acolor1[1]))
- + {
- + return 0L;
- + }
- + acolor1[2].r = ((2 * acolor1[0].r) + acolor1[1].r + 1) / 3;
- + acolor1[2].g = ((2 * acolor1[0].g) + acolor1[1].g + 1) / 3;
- + acolor1[2].b = ((2 * acolor1[0].b) + acolor1[1].b + 1) / 3;
- + acolor1[3].r = (acolor1[0].r + (2 * acolor1[1].r) + 1) / 3;
- + acolor1[3].g = (acolor1[0].g + (2 * acolor1[1].g) + 1) / 3;
- + acolor1[3].b = (acolor1[0].b + (2 * acolor1[1].b) + 1) / 3;
- + long l = 0L;
- + for (int i = 0; i < acolor.length; i++)
- + {
- + int j = 0x7fffffff;
- + int k = 0;
- + for (int i1 = 0; i1 < acolor1.length; i1++)
- + {
- + int j1 = distance(acolor[i], acolor1[i1]);
- + if (j1 < j)
- + {
- + j = j1;
- + k = i1;
- + }
- + }
- +
- + l |= k << (i * 2);
- + }
- +
- + return l;
- + }
- +
- + protected static int getPixel565(Color color)
- + {
- + int i = color.r >> 3;
- + int j = color.g >> 2;
- + int k = color.b >> 3;
- + return (i << 11) | (j << 5) | k;
- + }
- +
- + protected static Color getColor565(int i)
- + {
- + Color color = new Color();
- + color.r = (int) (i & 63488L) >> 11;
- + color.g = (int) (i & 2016L) >> 5;
- + color.b = (int) (i & 31L);
- + return color;
- + }
- +
- + protected static Color[] getColors888(int ai[])
- + {
- + Color acolor[] = new Color[ai.length];
- + for (int i = 0; i < ai.length; i++)
- + {
- + acolor[i] = new Color();
- + acolor[i].r = (int) (ai[i] & 0xff0000L) >> 16;
- + acolor[i].g = (int) (ai[i] & 65280L) >> 8;
- + acolor[i].b = (int) (ai[i] & 255L);
- + }
- +
- + return acolor;
- + }
- +
- + protected static int distance(Color color, Color color1)
- + {
- + return ((color1.r - color.r) * (color1.r - color.r)) + ((color1.g - color.g) * (color1.g - color.g)) + ((color1.b - color.b) * (color1.b - color.b));
- + }
- +}
- Index: trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/ImageData.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/ImageData.java (revision 427)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/ImageData.java (revision 428)
- +/*
- + * 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.gameserver.features;
- +
- +import java.awt.image.BufferedImage;
- +
- +public class ImageData
- +{
- + public ImageData()
- + {
- + }
- +
- + public BufferedImage image;
- + public String captchaText = "";
- + public int captchaID = 0;
- +}
- Index: trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/Captcha.java
- ===================================================================
- --- trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/Captcha.java (revision 427)
- +++ trunk/aCis_gameserver/java/net/sf/l2j/gameserver/features/Captcha.java (revision 428)
- +package net.sf.l2j.gameserver.features;
- +
- +import java.awt.Color;
- +import java.awt.Font;
- +import java.awt.FontMetrics;
- +import java.awt.Graphics2D;
- +import java.awt.geom.AffineTransform;
- +import java.awt.image.BufferedImage;
- +import java.util.Map;
- +import java.util.concurrent.ConcurrentHashMap;
- +
- +import net.sf.l2j.commons.random.Rnd;
- +import net.sf.l2j.gameserver.instancemanager.BotsPreventionManager.PlayerData;
- +import net.sf.l2j.gameserver.model.actor.instance.Player;
- +
- +/**
- + * Class that handles Generating and Sending Captcha Image to the Player
- + */
- +public class Captcha
- +{
- + private static final char[] CAPTCHA_TEXT_POSSIBILITIES =
- + {
- + 'A',
- + 'B',
- + 'C',
- + 'D',
- + 'E',
- + 'F',
- + 'G',
- + 'H',
- + 'K',
- + 'L',
- + 'M',
- + 'P',
- + 'R',
- + 'S',
- + 'T',
- + 'U',
- + 'W',
- + 'X',
- + 'Y',
- + 'Z'
- + };
- + private static final int CAPTCHA_WORD_LENGTH = 5;
- +
- + private static final int CAPTCHA_MIN_ID = 19000;
- + private static final int CAPTCHA_MAX_ID = 25000;
- +
- + Captcha()
- + {
- + }
- +
- + public static Captcha getInstance()
- + {
- + return SingletonHolder._instance;
- + }
- +
- + private static class SingletonHolder
- + {
- + protected static final Captcha _instance = new Captcha();
- + }
- +
- + public void generateCaptcha(PlayerData container, Player target)
- + {
- + int captchaId = generateRandomCaptchaId();
- + char[] captchaText = generateCaptchaText();
- +
- + container.image = generateCaptcha(captchaText);
- + // PledgeCrest packet = new PledgeCrest(captchaId, DDSConverter.convertToDDS(image).array());
- + // target.sendPacket(packet);
- +
- + container.captchaID = captchaId;
- + container.captchaText = String.valueOf(captchaText);
- + }
- + char[] captchaText;
- + int captchaId;
- +
- + public synchronized Map<Integer, ImageData> createImageList()
- + {
- + Map<Integer, ImageData> _imageMap = new ConcurrentHashMap<>();
- + for (int i = 0; i < 1000; i++)
- + {
- + do
- + {
- + captchaId = generateRandomCaptchaId();
- + captchaText = generateCaptchaText();
- + }
- + while (!_imageMap.isEmpty() && _imageMap.values().stream().anyMatch(txt -> txt.captchaText.equals(String.valueOf(captchaText))) || _imageMap.values().stream().anyMatch(s -> s.captchaID == captchaId));
- + ImageData dt = new ImageData();
- + dt.captchaID = captchaId;
- + dt.captchaText = String.valueOf(captchaText);
- + dt.image = generateCaptcha(captchaText);
- + _imageMap.put(i, dt);
- + }
- + return _imageMap;
- + }
- +
- + private static char[] generateCaptchaText()
- + {
- + char[] text = new char[CAPTCHA_WORD_LENGTH];
- + for (int i = 0; i < CAPTCHA_WORD_LENGTH; i++)
- + text[i] = CAPTCHA_TEXT_POSSIBILITIES[Rnd.get(CAPTCHA_TEXT_POSSIBILITIES.length)];
- + return text;
- + }
- +
- + private static int generateRandomCaptchaId()
- + {
- + return Rnd.get(CAPTCHA_MIN_ID, CAPTCHA_MAX_ID);
- + }
- +
- + public static BufferedImage generateCaptcha(char[] text)
- + {
- + Color textColor = new Color(38, 213, 30);
- + Color circleColor = new Color(73, 100, 151);
- + Font textFont = new Font("comic sans ms", Font.BOLD, 24);
- + int charsToPrint = 5;
- + int width = 256;
- + int height = 64;
- + int circlesToDraw = 8;
- + float horizMargin = 20.0f;
- + double rotationRange = 0.7; // this is radians
- + BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- +
- + Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
- +
- + // Draw an oval
- + g.setColor(new Color(30, 31, 31));
- + g.fillRect(0, 0, width, height);
- +
- + g.setColor(circleColor);
- + for (int i = 0; i < circlesToDraw; i++)
- + {
- + int circleRadius = (int) (Math.random() * height / 2.0);
- + int circleX = (int) (Math.random() * width - circleRadius);
- + int circleY = (int) (Math.random() * height - circleRadius);
- + g.drawOval(circleX, circleY, circleRadius * 2, circleRadius * 2);
- + }
- +
- + g.setColor(textColor);
- + g.setFont(textFont);
- +
- + FontMetrics fontMetrics = g.getFontMetrics();
- + int maxAdvance = fontMetrics.getMaxAdvance();
- + int fontHeight = fontMetrics.getHeight();
- +
- + float spaceForLetters = -horizMargin * 2.0F + width;
- + float spacePerChar = spaceForLetters / (charsToPrint - 1.0f);
- +
- + for (int i = 0; i < charsToPrint; i++)
- + {
- + char characterToShow = text[i];
- +
- + // this is a separate canvas used for the character so that
- + // we can rotate it independently
- + int charWidth = fontMetrics.charWidth(characterToShow);
- + int charDim = Math.max(maxAdvance, fontHeight);
- + int halfCharDim = charDim / 2;
- +
- + BufferedImage charImage = new BufferedImage(charDim, charDim, BufferedImage.TYPE_INT_ARGB);
- + Graphics2D charGraphics = charImage.createGraphics();
- + charGraphics.translate(halfCharDim, halfCharDim);
- + double angle = (Math.random() - 0.5) * rotationRange;
- + charGraphics.transform(AffineTransform.getRotateInstance(angle));
- + charGraphics.translate(-halfCharDim, -halfCharDim);
- + charGraphics.setColor(textColor);
- + charGraphics.setFont(textFont);
- +
- + int charX = (int) (0.5 * charDim - 0.5 * charWidth);
- + charGraphics.drawString(String.valueOf(characterToShow), charX, (charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent());
- +
- + float x = horizMargin + spacePerChar * i - charDim / 2.0f;
- + int y = (height - charDim) / 2;
- + g.drawImage(charImage, (int) x, y, charDim, charDim, null, null);
- +
- + charGraphics.dispose();
- + }
- +
- + g.dispose();
- +
- + return bufferedImage;
- + }
- +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement