Anti-Bot Protection For L2J

Iniciado por Swarlog, Jun 25, 2025, 08:59 PM

Tema anterior - Siguiente tema

Swarlog

CitarAnti-Bot.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.l2revive.antibot;

import com.l2revive.CustomConfig;
import com.l2revive.util.Util;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Logger;
import net.sf.l2j.Config;
import net.sf.l2j.gameserver.ThreadPoolManager;
import net.sf.l2j.gameserver.model.L2Object;
import net.sf.l2j.gameserver.model.actor.L2Character;
import net.sf.l2j.gameserver.model.actor.L2Summon;
import net.sf.l2j.gameserver.model.actor.instance.L2GrandBossInstance;
import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
import net.sf.l2j.gameserver.model.actor.instance.L2RaidBossInstance;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
import net.sf.l2j.gameserver.skills.AbnormalEffect;
import net.sf.l2j.gameserver.util.IllegalPlayerAction;

public class AntiBot {

    private static final Logger _log = Logger.getLogger(AntiBot.class.getName());
    private CustomConfig _config;
    private Map<L2PcInstance, BotResults> _players;// player=>BotResults(success/fail)
    private Map<L2PcInstance, String> _codes;
    protected Map<L2PcInstance, BotEye> _activeEyes;

    public static AntiBot getInstance() {
        return SingletonHolder._instance;
    }

    public AntiBot() {
        _log.info("AntiBot: Loading...");
        _players = new HashMap<>();
        _codes = new HashMap<>();
        _activeEyes = new HashMap<>();
    }

    public void setConfig(CustomConfig config) {
        _config = config;
        String triggerChance = getConfig().getString("AntiBotTriggerChance");
        if (triggerChance == null) {
            _log.info("AntiBot: #setConfig invalid value for AntiBotTriggerChance; defaulting to 3.");
            getConfig().set("TriggerChance", "3");
        }
        String checkInterval = getConfig().getString("AntiBotReCheckInterval");
        if (checkInterval == null) {
            _log.info("AntiBot: #setConfig invalid value for AntiBotReCheckInterval; defaulting to 60.");
            getConfig().set("AntiBotReCheckInterval", "60");
        }
    }

    private CustomConfig getConfig() {
        return _config;
    }

    public void add(L2PcInstance player) {
        _players.put(player, new BotResults(0, 0));
        player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_SYSMSG_RED).addString("AntiBot: Initialized Successfully."));
    }

    public void remove(L2PcInstance player) {
        _players.remove(player);
    }

    public void onKill(L2Character character) {
        L2PcInstance player = null;
        L2Object target = (character != null) ? character.getTarget() : null;
        if (character instanceof L2PcInstance) {
            player = (L2PcInstance) character;
        } else if (character instanceof L2Summon) {
            player = ((L2Summon) character).getActingPlayer();
        }
        if (player == null) {
            _log.info("AntiBot: #onKill for null.");
            return;
        }
        /*
         * note: below disabled anti-bot on raids to prevent item stealing.
         */
        if (target instanceof L2RaidBossInstance || target instanceof L2GrandBossInstance) {
            return;
        }
        /*
         * note: below disabled anti-bot on players and summons to prevent pvp interruption.
         */
        if (target instanceof L2PcInstance || target instanceof L2Summon) {
            return;
        }
        if (!_players.containsKey(player)) {
            _players.put(player, new BotResults(0, 0));
            triggerCaptcha(player, true);
        }
        int triggerChance = getConfig().getInteger("AntiBotTriggerChance");
        if ((Math.random() * 100) < triggerChance && !_activeEyes.containsKey(player)) {
            triggerCaptcha(player, true);
        }
    }

    private void triggerCaptcha(L2PcInstance player, boolean setEffect) {
        int id = (int) ((Math.random() * 1000) + 1);
        if (id < 100) {
            id = id + 100;
        }
        String code = String.valueOf(id);
        //_log.info("code=" + code);
        _codes.put(player, code);
        DDSConverter.sendImage(player, id, DDSConverter.generateImage(code));
        //DDSConverter.sendImage(player, id, "data/images/image.png");
        int seconds = getConfig().getInteger("AntiBotReCheckInterval");
        String html = "<html><title>AntiBot</title><body><center><br><br>"
                + "<font color=\"AA00AA\">L2Makai Anti Bot System</font><br><br>"
                + "<img src=\"Crest.crest_" + Config.SERVER_ID + "_" + id + "\" width=128 height=32><br>"
                + "<edit width=120 var=\"code\"><br>"
                + "<button action=\"bypass -h antibot $code\" value=\"Submit Code\" width=75 height=21 back=\"L2UI_ch3.Btn1_normalOn\" fore=\"L2UI_ch3.Btn1_normal\">"
                + "<br><br>If you close this window, use <font color=\"LEVEL\">/code</font><br>"
                + "You have <font color=\"LEVEL\">" + seconds + " seconds</font> to complete the captcha!<br>"
                + "<a action=\"bypass -h antibot refresh\"><font color=\"990099\">Refresh Image Above</font></a><br>"
                + "</center></body></html>";
        Util.sendRawHtml(player, html);
        if (setEffect) {
            player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_SYSMSG_RED).addString("AntiBot: /code"));
            ((L2Character) player).startAbnormalEffect(AbnormalEffect.FIREROOT_STUN);
            player.setIsImmobilized(true);
            player.setIsInvul(true);
            _activeEyes.put(player, new BotEye(player, seconds));
        }
    }

    public void show(L2PcInstance player) {
        if (_activeEyes.containsKey(player)) {
            triggerCaptcha(player, false);
        }
    }

    public void validate(L2PcInstance player, String code) {
        //_log.log(Level.INFO, "validate={0}", code);
        code = code.trim();
        if (code == null || code.equalsIgnoreCase("refresh")) {
            triggerCaptcha(player, false);
            return;
        }
        String valid = _codes.get(player);
        boolean status = false;
        if (valid != null && valid.equalsIgnoreCase(code)) {
            player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_SYSMSG_RED).addString("AntiBot: Success! You have also been healed."));
            ((L2Character) player).stopAbnormalEffect(AbnormalEffect.FIREROOT_STUN);
            player.setIsImmobilized(false);
            player.setIsInvul(false);
            player.setCurrentHp(player.getMaxHp());
            if (_activeEyes.containsKey(player)) {
                _activeEyes.remove(player).cancel();
            }
            status = true;
        } else {
            player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_SYSMSG_RED).addString("AntiBot: Incorrect! Please try again."));
            triggerCaptcha(player, false);
        }
        BotResults res = _players.get(player);
        _players.put(player, new BotResults(res._success + (status ? 1 : 0), res._fails + (!status ? 1 : 0)));
    }

    private static class SingletonHolder {

        protected static final AntiBot _instance = new AntiBot();
    }

    public static final class BotResults {

        public final int _success;
        public final int _fails;

        public BotResults(int success, int fails) {
            _success = success;
            _fails = fails;
        }
    }

    private final class BotEye implements Runnable {

        private ScheduledFuture _task;
        private int _delay;
        private L2PcInstance _player;

        public BotEye(L2PcInstance player, int delay) {
            _player = player;
            _delay = delay;
            run();
        }

        /*
         * if we reach here, then the player did not enter the code intime.
         */
        @Override
        public void run() {
            if (_delay < 1) {
                net.sf.l2j.gameserver.util.Util.handleIllegalPlayerAction(_player, "Player " + _player.getName() + " did not enter the antibot captcha intime.", IllegalPlayerAction.PUNISH_KICK);
                return;
            }
            handleTick();
            _task = ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
            _delay--;
        }

        public void cancel() {
            if (_task != null) {
                _task.cancel(true);
            }
        }

        private void handleTick() {
            switch (_delay) {
                case 30:
                case 10:
                case 5:
                case 4:
                case 3:
                case 2:
                case 1:
                    Util.sendMessageInBlue(_player, "AntiBot: You have " + _delay + " seconds to complete the captcha.");
                    break;
            }
        }
    }
}

CitarDDSConverter.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.l2revive.antibot;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Random;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
import net.sf.l2j.gameserver.network.serverpackets.PledgeCrest;

public class DDSConverter {

    private 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(File file) throws IOException {
        if (file == null) {
            String s = "nullValue.FileIsNull";
            _log.severe(s);
            throw new IllegalArgumentException(s);
        }
        if (!file.exists() || !file.canRead()) {
            String s1 = "DDSConverter.NoFileOrNoPermission";
            _log.severe(s1);
            throw new IllegalArgumentException(s1);
        }
        BufferedImage bufferedimage = ImageIO.read(file);
        if (bufferedimage == null) {
            return null;
        }
        if (bufferedimage.getColorModel().hasAlpha()) {
            return convertToDxt3(bufferedimage);
        }
        return convertToDxt1NoTransparency(bufferedimage);
    }

    public static ByteBuffer convertToDDS(BufferedImage bufferedimage) {
        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));
    }

    public static BufferedImage scaleImage(BufferedImage img, int width, int height, java.awt.Color background) {
        int imgWidth = img.getWidth();
        int imgHeight = img.getHeight();
        if (imgWidth * height < imgHeight * width) {
            width = imgWidth * height / imgHeight;
        } else {
            height = imgHeight * width / imgWidth;
        }
        BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = newImage.createGraphics();
        try {
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g.setBackground(background);
            g.clearRect(0, 0, width, height);
            g.drawImage(img, 0, 0, width, height, null);
        } finally {
            g.dispose();
        }
        return newImage;
    }

    /*public static BufferedImage generateImage(String text) {
     BufferedImage img = new BufferedImage(128, 32, BufferedImage.TYPE_INT_RGB);
     java.awt.Color bgColor = java.awt.Color.GREEN;
     Graphics2D g2d = img.createGraphics();
     g2d.drawImage(img, 0, 0, null);
     g2d.setPaint(java.awt.Color.RED);
     g2d.setFont(new Font("Serif", Font.BOLD, 20));
     FontMetrics fm = g2d.getFontMetrics();
     int x = img.getWidth() - fm.stringWidth(text) - 50;
     int y = fm.getHeight() - 4;
     g2d.setBackground(bgColor);
     g2d.drawString(text, x, y);
     g2d.dispose();
     return img;
     }*/
    public static BufferedImage generateImage(String text) {
        BufferedImage img = new BufferedImage(128, 32, BufferedImage.TYPE_INT_RGB);
        java.awt.Color bgColor = new java.awt.Color(100, 100, 100);
        java.awt.Color textColor = new java.awt.Color(160, 160, 160);
        java.awt.Color noiseColor = new java.awt.Color(130, 130, 130);
        //===
        Random rnd = new Random();
        switch (rnd.nextInt(10)) {
            case 0:
            case 1://green
                bgColor = new java.awt.Color(0, 100, 0);
                textColor = new java.awt.Color(0, 150, 0);
                noiseColor = new java.awt.Color(0, 125, 0);
                break;
            case 2:
            case 3://blue
                bgColor = new java.awt.Color(0, 0, 100);
                textColor = new java.awt.Color(0, 0, 170);
                noiseColor = new java.awt.Color(0, 0, 125);
                break;
            case 4:
            case 5://pink
                bgColor = new java.awt.Color(100, 0, 100);
                textColor = new java.awt.Color(150, 0, 150);
                noiseColor = new java.awt.Color(125, 0, 125);
                break;
            case 6:
            case 7:
            case 8:
            case 9:
        }
        //===
        Graphics2D backColor = img.createGraphics();
        backColor.setPaint(bgColor);
        backColor.fillRect(0, 0, img.getWidth(), img.getHeight());
        backColor.dispose();
        //===
        for (int i = 0; i < 20; i++) {
            Graphics2D g = img.createGraphics();
            g.setColor(noiseColor);
            int radius = rnd.nextInt(10) + 4;
            int x = rnd.nextInt(128) + 1;
            int y = rnd.nextInt(32) + 1;
            g.fillOval(x, y, radius, radius);
        }
        //===
        Graphics2D g2d = img.createGraphics();
        g2d.drawImage(img, 0, 0, null);
        g2d.setPaint(textColor);
        int fontSize = rnd.nextInt(18) + 12;
        g2d.setFont(new Font("Serif", Font.BOLD, fontSize));
        FontMetrics fm = g2d.getFontMetrics();
        int x2 = img.getWidth() - fm.stringWidth(text) - rnd.nextInt(120 - fontSize);
        if (fontSize < 12) {
            fontSize = 12;
        }
        int y2 = fm.getHeight() - (fontSize / 4);//about 4
        g2d.drawString(text, x2, y2);
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.dispose();
        return img;
    }

    public static void sendImage(L2PcInstance player, int id, BufferedImage image) {
        try {
            PledgeCrest packet = new PledgeCrest(id, DDSConverter.convertToDDS(image).array());
            player.sendPacket(packet);
        } catch (Exception e) {
        }
    }
}