mirror of
https://github.com/moparisthebest/MoparClassic
synced 2024-11-12 04:05:12 -05:00
Closes issue #130
This commit is contained in:
parent
469e4651fa
commit
1a59778484
10000
GameServer/conf/data/dictionary.txt
Normal file
10000
GameServer/conf/data/dictionary.txt
Normal file
File diff suppressed because it is too large
Load Diff
BIN
GameServer/conf/fonts/ADDSBP__.TTF
Normal file
BIN
GameServer/conf/fonts/ADDSBP__.TTF
Normal file
Binary file not shown.
BIN
GameServer/conf/fonts/Harakiri.ttf
Normal file
BIN
GameServer/conf/fonts/Harakiri.ttf
Normal file
Binary file not shown.
Binary file not shown.
BIN
GameServer/conf/fonts/IntellectaBodoned Trash.ttf
Normal file
BIN
GameServer/conf/fonts/IntellectaBodoned Trash.ttf
Normal file
Binary file not shown.
BIN
GameServer/conf/fonts/MiseryLovesCompanyDEMO.ttf
Normal file
BIN
GameServer/conf/fonts/MiseryLovesCompanyDEMO.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -94,4 +94,9 @@
|
||||
|
||||
<!-- This is displayed on login. Each line will be sent as a new message. Make sure you're using XML entities for things like <, new lines, etc. -->
|
||||
<entry key="MOTD">@yel@Welcome to MoparClassic Alpha! @red@Report all bugs on GitHub. @cya@Commands: ::town <townname>, ::item <id>, ::say <msg>, ::goto <name></entry>
|
||||
|
||||
<!-- This is the location of the captcha dictionary -->
|
||||
<entry key="captcha-dictionary">conf/data/dictionary.txt</entry>
|
||||
<!-- This is the directory that contains the fonts -->
|
||||
<entry key="font-dir">conf/fonts</entry>
|
||||
</properties>
|
||||
|
@ -48,6 +48,8 @@ public class Config {
|
||||
public static String DATA_SERVICE;
|
||||
public static String REPORT_HANDLER;
|
||||
public static String MOTD;
|
||||
public static String CAPTCHA_DICTIONARY;
|
||||
public static String FONT_DIR;
|
||||
|
||||
static {
|
||||
loadEnv();
|
||||
@ -144,6 +146,9 @@ public class Config {
|
||||
|
||||
MOTD = props.getProperty("MOTD");
|
||||
|
||||
CAPTCHA_DICTIONARY = props.getProperty("captcha-dictionary");
|
||||
FONT_DIR = props.getProperty("font-dir");
|
||||
|
||||
props.clear();
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,13 @@ import org.moparscape.msc.config.Constants;
|
||||
import org.moparscape.msc.config.Formulae;
|
||||
import org.moparscape.msc.gs.Instance;
|
||||
import org.moparscape.msc.gs.connection.RSCPacket;
|
||||
import org.moparscape.msc.gs.core.GameEngine;
|
||||
import org.moparscape.msc.gs.model.Bank;
|
||||
import org.moparscape.msc.gs.model.InvItem;
|
||||
import org.moparscape.msc.gs.model.Player;
|
||||
import org.moparscape.msc.gs.model.Shop;
|
||||
import org.moparscape.msc.gs.model.World;
|
||||
import org.moparscape.msc.gs.quest.Quest;
|
||||
import org.moparscape.msc.gs.tools.Captcha;
|
||||
|
||||
public class MiscPacketBuilder {
|
||||
/**
|
||||
@ -219,7 +219,7 @@ public class MiscPacketBuilder {
|
||||
*/
|
||||
public void sendEnterSleep() {
|
||||
player.setSleeping(true);
|
||||
byte[] image = GameEngine.getCaptcha().generateCaptcha(player);
|
||||
byte[] image = Captcha.generateCaptcha(player);
|
||||
RSCPacketBuilder s = new RSCPacketBuilder();
|
||||
s.setID(206);
|
||||
s.addBytes(image, 0, image.length);
|
||||
|
@ -24,7 +24,6 @@ import org.moparscape.msc.gs.model.snapshot.Snapshot;
|
||||
import org.moparscape.msc.gs.phandler.PacketHandler;
|
||||
import org.moparscape.msc.gs.phandler.PacketHandlerDef;
|
||||
import org.moparscape.msc.gs.plugins.dependencies.NpcAI;
|
||||
import org.moparscape.msc.gs.tools.Captcha;
|
||||
import org.moparscape.msc.gs.util.Logger;
|
||||
|
||||
/**
|
||||
@ -33,16 +32,11 @@ import org.moparscape.msc.gs.util.Logger;
|
||||
*/
|
||||
public final class GameEngine extends Thread {
|
||||
|
||||
private static Captcha captcha;
|
||||
/**
|
||||
* World instance
|
||||
*/
|
||||
private static final World world = Instance.getWorld();
|
||||
|
||||
public static Captcha getCaptcha() {
|
||||
return captcha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for updating all connected clients
|
||||
*/
|
||||
@ -88,8 +82,6 @@ public final class GameEngine extends Thread {
|
||||
* Constructs a new game engine with an empty packet queue.
|
||||
*/
|
||||
public GameEngine() {
|
||||
captcha = new Captcha();
|
||||
captcha.init();
|
||||
packetQueue = new PacketQueue<RSCPacket>();
|
||||
try {
|
||||
loadPacketHandlers();
|
||||
|
@ -4,177 +4,121 @@ import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.moparscape.msc.config.Config;
|
||||
import org.moparscape.msc.gs.model.Player;
|
||||
import org.moparscape.msc.gs.util.Logger;
|
||||
|
||||
public class Captcha {
|
||||
/*
|
||||
* ArrayList that includes the preset colours.
|
||||
*/
|
||||
|
||||
public ArrayList<Color> colors = new ArrayList<Color>();
|
||||
/*
|
||||
* Boolean to decide whether to draw the grid on top or not
|
||||
*/
|
||||
public boolean drawGrid = true;
|
||||
/*
|
||||
* String that represents the folder to load the fonts from
|
||||
*/
|
||||
public String fontFolder = "." + File.separator + "conf" + File.separator
|
||||
+ "fonts" + File.separator;
|
||||
private final int LETTERS_MAX = 5;
|
||||
private final int LETTERS_MIN = 4;
|
||||
private final int LINES_MAX = 10;
|
||||
private final int LINES_MIN = 5;
|
||||
/*
|
||||
* Font array that includes all the loaded fonts with a preset size (between
|
||||
* 25 and 30)
|
||||
*/
|
||||
public Font loadedFonts[];
|
||||
private Random rand = new Random();
|
||||
private final int SQUARES_MAX = 13;
|
||||
/*
|
||||
* Settings to disable OCRs
|
||||
*/
|
||||
private final int SQUARES_MIN = 7;
|
||||
private final static Font[] fonts = new Font[4];
|
||||
private final static Random random = new Random();
|
||||
private final static String[] words;
|
||||
|
||||
/*
|
||||
* Boolean that defines if we should display what Font we loaded.
|
||||
*/
|
||||
public boolean verboseLoad = false;
|
||||
static {
|
||||
|
||||
public byte[] generateCaptcha(Player p) {
|
||||
BufferedImage image = new BufferedImage(307, 49,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D gfx = image.createGraphics();
|
||||
String captcha = "";
|
||||
|
||||
gfx.setColor(Color.white);
|
||||
gfx.fillRect(0, 0, 308, 52);
|
||||
|
||||
int howManyLetters = random(LETTERS_MIN, LETTERS_MAX);
|
||||
for (int i = 1; i <= howManyLetters; i++) {
|
||||
char temp = generateLetter();
|
||||
if (temp == 'i' || temp == 'l') {
|
||||
temp = 'q'; // ez fix.
|
||||
}
|
||||
captcha += temp;
|
||||
gfx.setColor(colors.get(random(0, colors.size() - 1)));
|
||||
gfx.setFont(loadedFonts[random(0, loadedFonts.length - 1)]);
|
||||
double shear = (rand.nextDouble()) - 0.5;
|
||||
gfx.shear(shear, 0);
|
||||
gfx.drawString(String.valueOf(temp), i * random(40, 45),
|
||||
random(30, 40));
|
||||
gfx.shear(-shear, 0);
|
||||
}
|
||||
|
||||
int howManySquares = random(SQUARES_MIN, SQUARES_MAX);
|
||||
for (int i = 0; i < howManySquares; i++) // Draw the squares, math by
|
||||
// xEnt.
|
||||
{
|
||||
gfx.setColor(colors.get(random(0, colors.size() - 1)));
|
||||
gfx.drawRect((int) random(0, image.getWidth() - 80),
|
||||
(int) random(0, image.getHeight()), 3, 3);
|
||||
}
|
||||
|
||||
int howManyLines = random(LINES_MIN, LINES_MAX);
|
||||
for (int i = 0; i < howManyLines; i++) // Draw the lines, math by xEnt.
|
||||
{
|
||||
gfx.setColor(colors.get(random(0, colors.size() - 1)));
|
||||
int x = random(0, image.getWidth() - 80);
|
||||
int y = random(0, image.getHeight());
|
||||
gfx.drawLine(x, y, x + random(0, 30), y - random(0, 30));
|
||||
}
|
||||
|
||||
if (drawGrid) // Draws the gray grid
|
||||
{
|
||||
gfx.setColor(Color.gray);
|
||||
gfx.drawLine(0, 13, image.getWidth(), 13);
|
||||
gfx.drawLine(0, 26, image.getWidth(), 26);
|
||||
gfx.drawLine(0, 39, image.getWidth(), 39);
|
||||
for (int i = 1; i < (int) (image.getWidth() / 10); i++) {
|
||||
gfx.drawLine(20 * i, 0, 20 * i, image.getHeight());
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] returnVal = null;
|
||||
// Load fonts
|
||||
try {
|
||||
ImageIO.write(image, "PNG", baos);
|
||||
returnVal = baos.toByteArray();
|
||||
// DataOutputStream out = new DataOutputStream(new
|
||||
// FileOutputStream("newcaptchas/" + captcha + ".png"));
|
||||
// out.write(returnVal);
|
||||
String fontDir = Config.FONT_DIR;
|
||||
fonts[0] = Font.createFont(Font.TRUETYPE_FONT,
|
||||
new File(fontDir, "Harakiri.ttf")).deriveFont(30f);
|
||||
fonts[1] = Font.createFont(Font.TRUETYPE_FONT,
|
||||
new File(fontDir, "IntellectaBodoned Trash.ttf"))
|
||||
.deriveFont(30f);
|
||||
fonts[2] = Font.createFont(Font.TRUETYPE_FONT,
|
||||
new File(fontDir, "MiseryLovesCompanyDEMO.ttf"))
|
||||
.deriveFont(20f);
|
||||
fonts[3] = Font.createFont(Font.TRUETYPE_FONT,
|
||||
new File(fontDir, "ADDSBP__.TTF")).deriveFont(20f);
|
||||
} catch (Exception e) {
|
||||
Logger.error("Font loading error: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Load word list
|
||||
List<String> wordList = new ArrayList<String>();
|
||||
File file = new File(Config.CAPTCHA_DICTIONARY);
|
||||
FileInputStream in = null;
|
||||
BufferedReader reader = null;
|
||||
FileChannel chan = null;
|
||||
try {
|
||||
in = new FileInputStream(file);
|
||||
chan = in.getChannel();
|
||||
reader = new BufferedReader(new InputStreamReader(in));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
wordList.add(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
chan.close();
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
gfx.dispose();
|
||||
p.setSleepword(captcha);
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
private char generateLetter() {
|
||||
char returnVal = '-';
|
||||
switch (random(0, 1)) {
|
||||
case 0:
|
||||
returnVal = (char) random(65, 89);
|
||||
break;
|
||||
case 1:
|
||||
returnVal = (char) random(97, 121);
|
||||
break;
|
||||
}
|
||||
return returnVal;
|
||||
words = wordList.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
loadFonts();
|
||||
colors.clear();
|
||||
colors.add(Color.BLUE);
|
||||
colors.add(Color.GREEN);
|
||||
colors.add(Color.GRAY);
|
||||
colors.add(Color.BLACK);
|
||||
colors.add(Color.RED);
|
||||
colors.add(Color.PINK);
|
||||
colors.add(Color.DARK_GRAY);
|
||||
public static byte[] generateCaptcha(Player p) {
|
||||
BufferedImage image = new BufferedImage(255, 40,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = image.createGraphics();
|
||||
g.setColor(Color.black);
|
||||
g.fillRect(0, 0, 255, 40);
|
||||
g.setColor(Color.white);
|
||||
String word = getWord();
|
||||
p.setSleepword(word);
|
||||
int lastx = 5;
|
||||
for (char c : word.toCharArray()) {
|
||||
Font font = fonts[random.nextInt(fonts.length)];
|
||||
char chr = Character.toUpperCase(c);
|
||||
g.setFont(font);
|
||||
// y = 35 +- 5
|
||||
g.drawString(String.valueOf(chr), lastx, 35 + 5 * randomSignFlip());
|
||||
// Width +- an element of (0 through 5)
|
||||
lastx += g.getFontMetrics().charWidth(chr)
|
||||
+ randomSignFlip() * random.nextInt(6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads fonts from a folder to a font array
|
||||
*/
|
||||
public void loadFonts() {
|
||||
File fontFolderFile = new File(fontFolder);
|
||||
String[] fonts = fontFolderFile.list();
|
||||
loadedFonts = new Font[fonts.length];
|
||||
for (int i = 0; i < fonts.length; i++) {
|
||||
g.dispose();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte bytes[] = null;
|
||||
try {
|
||||
FileInputStream fontStream = new FileInputStream(fontFolder
|
||||
+ fonts[i]);
|
||||
Font temp = java.awt.Font.createFont(
|
||||
java.awt.Font.TRUETYPE_FONT, fontStream);
|
||||
loadedFonts[i] = temp.deriveFont(Float.valueOf(random(35, 40)));
|
||||
if (verboseLoad) {
|
||||
Logger.println("Loaded font: "
|
||||
+ loadedFonts[i].getFontName());
|
||||
ImageIO.write(image, "png", baos);
|
||||
bytes = baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
Logger.error("Error generating sleep word: " + ioe.getMessage());
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Logger.println("Loaded " + fonts.length + " fonts.");
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a random number within the given bounds
|
||||
*/
|
||||
public int random(int low, int high) {
|
||||
return low + rand.nextInt(high - low + 1);
|
||||
private static int randomSignFlip() {
|
||||
return random.nextBoolean() ? 1 : -1;
|
||||
}
|
||||
|
||||
public static String getWord() {
|
||||
int row = random.nextInt(words.length);
|
||||
return words[row];
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
package org.moparscape.msc.gs.tools;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.HeadlessException;
|
||||
import java.awt.Image;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
public class PaintCaptcha {
|
||||
|
||||
private final static boolean GRAPH = true;
|
||||
private final static Color GRAPH_COLOR = Color.GRAY;
|
||||
private final static int LINES = 10;
|
||||
/**
|
||||
* @author xEnt
|
||||
* @info Paints over an Image(Captcha) to make it more secure, with Lines,
|
||||
* Squares and a Graph.
|
||||
*/
|
||||
|
||||
private final static int SQUARES_MAX = 25;
|
||||
private final static int SQUARES_MIN = 10;
|
||||
|
||||
/*
|
||||
* public static void main(String [] args) throws Exception { Image img =
|
||||
* Toolkit.getDefaultToolkit().getImage("C:\\heh.png");
|
||||
* ImageIO.write(Img.toBufferedImage(secure(img)), "png", new
|
||||
* File("C:\\roflrofl.png")); }
|
||||
*/
|
||||
|
||||
public static long randomNumber(int min, int max) {
|
||||
return Math.round((Math.random() * (max - min)) + min);
|
||||
}
|
||||
|
||||
public static BufferedImage secure(BufferedImage b) {
|
||||
try {
|
||||
|
||||
// BufferedImage b = toBufferedImage(img);
|
||||
Graphics2D gfx = b.createGraphics();
|
||||
gfx.setPaintMode();
|
||||
|
||||
// Draw the Squares.
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < (int) randomNumber(SQUARES_MIN, SQUARES_MAX); i++) {
|
||||
Color randomColor = Color.getHSBColor(random.nextFloat(), 1.0F,
|
||||
1.0F);
|
||||
gfx.setColor(randomColor);
|
||||
gfx.drawRect((int) randomNumber(0, b.getWidth() - 80),
|
||||
(int) randomNumber(0, b.getHeight()), 3, 3);
|
||||
}
|
||||
|
||||
// Draw the Lines.
|
||||
gfx.setColor(Color.ORANGE);
|
||||
for (int i = 0; i < LINES; i++) {
|
||||
int x = (int) randomNumber(0, b.getWidth() - 80);
|
||||
int y = (int) randomNumber(0, b.getHeight());
|
||||
gfx.drawLine(x, y, x + (int) randomNumber(0, 30), y
|
||||
- (int) randomNumber(0, 30));
|
||||
}
|
||||
|
||||
if (GRAPH) {
|
||||
// Graph, Lines from Top to Bottom.
|
||||
gfx.setColor(GRAPH_COLOR);
|
||||
for (int i = 0; i < 17; i++) {
|
||||
gfx.drawLine(5 + i * 15, b.getHeight(), 5 + i * 15, 0);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
gfx.drawLine(b.getWidth(), i * 14, 0, i * 14);
|
||||
}
|
||||
}
|
||||
|
||||
gfx.dispose();
|
||||
return b;
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static BufferedImage toBufferedImage(Image image) {
|
||||
if (image instanceof BufferedImage) {
|
||||
return (BufferedImage) image;
|
||||
}
|
||||
|
||||
// This code ensures that all the pixels in the image are loaded
|
||||
image = new ImageIcon(image).getImage();
|
||||
|
||||
// Determine if the image has transparent pixels; for this method's
|
||||
// implementation, see e661 Determining If an Image Has Transparent
|
||||
// Pixels
|
||||
boolean hasAlpha = false;
|
||||
|
||||
// Create a buffered image with a format that's compatible with the
|
||||
// screen
|
||||
BufferedImage bimage = null;
|
||||
GraphicsEnvironment ge = GraphicsEnvironment
|
||||
.getLocalGraphicsEnvironment();
|
||||
try {
|
||||
// Determine the type of transparency of the new buffered image
|
||||
int transparency = Transparency.OPAQUE;
|
||||
if (hasAlpha) {
|
||||
transparency = Transparency.BITMASK;
|
||||
}
|
||||
|
||||
// Create the buffered image
|
||||
GraphicsDevice gs = ge.getDefaultScreenDevice();
|
||||
GraphicsConfiguration gc = gs.getDefaultConfiguration();
|
||||
bimage = gc.createCompatibleImage(image.getWidth(null),
|
||||
image.getHeight(null), transparency);
|
||||
} catch (HeadlessException e) {
|
||||
// The system does not have a screen
|
||||
}
|
||||
|
||||
if (bimage == null) {
|
||||
// Create a buffered image using the default color model
|
||||
int type = BufferedImage.TYPE_INT_RGB;
|
||||
if (hasAlpha) {
|
||||
type = BufferedImage.TYPE_INT_ARGB;
|
||||
}
|
||||
bimage = new BufferedImage(image.getWidth(null),
|
||||
image.getHeight(null), type);
|
||||
}
|
||||
|
||||
// Copy image to buffered image
|
||||
Graphics g = bimage.createGraphics();
|
||||
|
||||
// Paint the image onto the buffered image
|
||||
g.drawImage(image, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
return bimage;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user