/*
Copyright 2012 Jan Ove Saltvedt
This file is part of KBot.
KBot 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.
KBot 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 KBot. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright � 2010 Jan Ove Saltvedt.
* All rights reserved.
*/
package com.kbotpro.debuggers;
import com.kbotpro.hooks.Client;
import com.kbotpro.hooks.MapData;
import com.kbotpro.hooks.TileData;
import com.kbotpro.scriptsystem.events.PaintEventListener;
import com.kbotpro.scriptsystem.fetch.Objects;
import com.kbotpro.scriptsystem.runnable.Debugger;
import com.kbotpro.scriptsystem.wrappers.PhysicalObject;
import com.kbotpro.scriptsystem.wrappers.Tile;
import com.kbotpro.ui.FieldWatcher;
import org.apache.log4j.Logger;
import javax.imageio.ImageIO;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
* User: Jan Ove Saltvedt
* Date: Feb 23, 2010
* Time: 5:46:03 PM
* To change this template use File | Settings | File Templates.
*/
public class MapDebugger extends Debugger implements PaintEventListener {
private boolean shallRun = false;
private Tile currentTile;
private UI ui;
/**
* Gets the name shown in the debugs menu
*
* @return String containing name
*/
@Override
public String getName() {
return "Map Debugger";
}
/**
* Is called before the debugger starts to check if it can run.
*
* @return Returns a boolean indicating if the service can be started or not
*/
@Override
public boolean canStart() {
return true;
}
/**
* Is called right before the run() gets called
*/
@Override
public void onStart() {
shallRun = true;
currentTile = getLocation();
EventQueue.invokeLater(new Runnable() {
public void run() {
ui = new UI();
ui.xSpinner.setValue(currentTile.getX());
ui.ySpinner.setValue(currentTile.getY());
ui.myPosButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
currentTile = getLocation();
ui.xSpinner.setValue(currentTile.getX());
ui.ySpinner.setValue(currentTile.getY());
}
});
ui.xSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
currentTile = new Tile((Integer) ui.xSpinner.getValue(), (Integer) ui.ySpinner.getValue());
}
});
ui.ySpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
currentTile = new Tile((Integer) ui.xSpinner.getValue(), (Integer) ui.ySpinner.getValue());
}
});
ui.reflectButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final Client client = getClient();
int x = currentTile.getX() - client.getBaseX();
int y = currentTile.getY() - client.getBaseY();
final TileData[][][] datas = client.getTileDataArray();
if (datas == null || datas.length < 1 || datas[0] == null) {
return;
}
TileData data = datas[0][x][y];
new FieldWatcher(data).setVisible(true);
}
});
ui.createMapButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
createMap();
}
});
ui.setVisible(true);
}
});
}
/**
* Is called to pause debugger.
*/
@Override
public void pause() {
}
/**
* Is called to stop the debugger.
* The debugger is than added to the cleanup queue and thread will be force killed if not deleted within 10 seconds.
*/
@Override
public void stop() {
shallRun = false;
ui.dispose();
}
/**
* You should implement the main loop here.
*/
@Override
public void run() {
while (shallRun) {
dumpData();
sleep(1000);
}
}
private void dumpData() {
final Client client = getClient();
final MapData[] datas = client.getMapDataArray();
final int currentPlane = client.getCurrentPlane();
for(int plane = 0; plane < datas.length; plane++){
final String mapDataPath = "map_data/" + currentPlane;
final File mapDataFolder = new File(mapDataPath);
if (!mapDataFolder.exists()) {
if (!mapDataFolder.mkdirs()) {
return;
}
}
int baseX = client.getBaseX();
int baseY = client.getBaseY();
final String mapPath = mapDataPath + "/" + baseX + "x" + baseY + "L-"+plane+".png";
if (new File(mapPath).exists()) {
return;
}
final BufferedImage image = generateMap(plane);
try {
ImageIO.write(image, "png", new File(mapPath));
} catch (IOException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
}
log("Wrote map to " + mapPath);
}
}
private void createMap() {
BufferedImage bufferedImage = generateMap(getClient().getCurrentPlane());
try {
ImageIO.write(bufferedImage, "png", new File("map.out.png"));
} catch (IOException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
}
}
private BufferedImage generateMap(int plane) {
final Client client = getClient();
MapData mapData = client.getMapDataArray()[plane];
final int[][] tileDataArray = mapData.getTileData();
final int width = 104 * 8;
final int height = 104 * 8;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
g.setColor(Color.black);
for (int x = 1; x < 105; x++) {
for (int y = 1; y < 105; y++) {
PhysicalObject[] physicalObjects = objects.getObjectsAt(x, y, Objects.MASK_INTERACTIVE);
if (physicalObjects != null && physicalObjects.length > 0) {
boolean foundDoor = false;
for (PhysicalObject object : physicalObjects) {
}
}
int tileData = tileDataArray[x][y];
if ((tileData & FULL_BLOCK) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.fillRect(screenX, screenY, 8, 8);
}
if ((tileData & BLOCKED_0_NORTH) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.drawLine(screenX, screenY, screenX + 8, screenY);
}
if ((tileData & BLOCKED_0_EAST) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.drawLine(screenX + 8, screenY, screenX + 8, screenY + 8);
}
if ((tileData & BLOCKED_0_SOUTH) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.drawLine(screenX, screenY + 8, screenX + 8, screenY + 8);
}
if ((tileData & BLOCKED_0_WEST) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.drawLine(screenX, screenY, screenX, screenY + 8);
}
if ((tileData & BLOCKED_0_NORTH_EAST) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.fillRect(screenX+7, screenY-1, 2, 2);
}
if ((tileData & BLOCKED_0_SOUTH_EAST) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.fillRect(screenX+7, screenY+7, 2, 2);
}
if ((tileData & BLOCKED_0_SOUTH_WEST) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.fillRect(screenX-1, screenY+7, 2, 2);
}
if ((tileData & BLOCKED_0_NORTH_WEST) != 0) {
int screenX = (x - 1) * 8;
int screenY = (y - 1) * 8;
screenY = height - screenY - 8;
g.fillRect(screenX-1, screenY-1, 2, 2);
}
}
}
return bufferedImage;
}
private final int BLOCKING_OBJECT = 0x100;
private final int BLOCKED_0_NORTH = 0x2;
private final int BLOCKED_0_NORTH_EAST = 0x4;
private final int BLOCKED_0_EAST = 0x8;
private final int BLOCKED_0_SOUTH_EAST = 0x10;
private final int BLOCKED_0_SOUTH = 0x20;
private final int BLOCKED_0_SOUTH_WEST = 0x40;
private final int BLOCKED_0_WEST = 0x80;
private final int BLOCKED_0_NORTH_WEST = 0x200;
private final int BLOCKED_1_NORTH = 0x400;
private final int BLOCKED_1_NORTH_EAST = 0x800;
private final int BLOCKED_1_EAST = 0x1000;
private final int BLOCKED_1_SOUTH_EAST = 0x2000;
private final int BLOCKED_1_SOUTH = 0x4000;
private final int BLOCKED_1_SOUTH_WEST = 0x8000;
private final int BLOCKED_1_WEST = 0x10000;
private final int BLOCKED_1_NORTH_WEST = 0x40000;
private final int BLOCKED_2_NORTH = 0x800000;
private final int BLOCKED_2_NORTH_EAST = 0x1000000;
private final int BLOCKED_2_EAST = 0x2000000;
private final int BLOCKED_2_SOUTH_EAST = 0x4000000;
private final int BLOCKED_2_SOUTH = 0x8000000;
private final int BLOCKED_2_SOUTH_WEST = 0x10000000;
private final int BLOCKED_2_WEST = 0x20000000;
private final int BLOCKED_2_NORTH_WEST = 0x80000000;
private final int BLOCK_0 = 0x100;
private final int BLOCK_1 = 0x40000;
private final int BLOCK_2 = 0x200000;
private final int BLOCK_3 = 0x40000000;
private final int FULL_BLOCK = /*BLOCK_0 | */BLOCK_1 | BLOCK_2 | BLOCK_3;
public void onRepaint(Graphics g) {
if (currentTile == null) {
return;
}
final int baseX = getClient().getBaseX();
final int baseY = getClient().getBaseY();
g.setColor(new Color(Color.blue.getRed(), Color.blue.getGreen(), Color.blue.getBlue(), 120));
int rsStartX = currentTile.getRegionalX(baseX);
int rsStartY = currentTile.getRegionalY(baseY);
int rsEndX = rsStartX + 256;
int rsEndY = rsStartY + 256;
Polygon polygon = new Polygon();
Point point = calculations.worldToScreen(rsStartX, rsStartY, 0);
Point p2 = calculations.worldToScreen(rsStartX-256, rsStartY-256, 0);
polygon.addPoint(p2.x, p2.y);
p2 = calculations.worldToScreen(rsStartX-256, rsStartY+256, 0);
polygon.addPoint(p2.x, p2.y);
p2 = calculations.worldToScreen(rsStartX+256, rsStartY+256, 0);
polygon.addPoint(p2.x, p2.y);
p2 = calculations.worldToScreen(rsStartX+256, rsStartY-256, 0);
polygon.addPoint(p2.x, p2.y);
g.fillPolygon(polygon);
g.setColor(Color.pink);
final Point mmPoint = calculations.tileToMinimap(currentTile);
g.fillOval(mmPoint.x - 2, mmPoint.y - 2, 4, 4);
try {
g.setColor(Color.WHITE);
final Client client = getClient();
MapData mapData = client.getMapDataArray()[client.getCurrentPlane()];
int x = currentTile.getX() - baseX + 1;
int y = currentTile.getY() - baseY + 1;
int tileData = mapData.getTileData()[x][y];
g.drawString("TileData (i): " + tileData, 20, 60);
String binaryTileData = Integer.toString(tileData, 2);
g.drawString("TileData (b): " + binaryTileData, 20, 80);
g.drawString("Dumping data is on", 20, 100);
int flagNum = 0;
int newTileData = tileData;
if ((newTileData & BLOCKED_0_NORTH) != 0) {
g.drawString("Blocked edge north", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_NORTH;
}
if ((newTileData & BLOCKED_0_NORTH_EAST) != 0) {
g.drawString("Blocked edge north east", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_NORTH_EAST;
}
if ((newTileData & BLOCKED_0_EAST) != 0) {
g.drawString("Blocked edge east", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_EAST;
}
if ((newTileData & BLOCKED_0_SOUTH_EAST) != 0) {
g.drawString("Blocked edge south east", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_SOUTH_EAST;
}
if ((newTileData & BLOCKED_0_SOUTH) != 0) {
g.drawString("Blocked edge south", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_SOUTH;
}
if ((newTileData & BLOCKED_0_SOUTH_WEST) != 0) {
g.drawString("Blocked edge south west", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_SOUTH_WEST;
}
if ((newTileData & BLOCKED_0_WEST) != 0) {
g.drawString("Blocked edge west", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_WEST;
}
if ((newTileData & BLOCKED_0_NORTH_WEST) != 0) {
g.drawString("Blocked north west", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ BLOCKED_0_NORTH_WEST;
}
if ((newTileData & (BLOCKED_1_NORTH | BLOCKED_2_NORTH)) != 0) {
g.drawString("Can not walk north", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_NORTH | BLOCKED_2_NORTH);
}
if ((newTileData & (BLOCKED_1_NORTH_EAST | BLOCKED_2_NORTH_EAST)) != 0) {
g.drawString("Can not walk north east", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_NORTH_EAST | BLOCKED_2_NORTH_EAST);
}
if ((newTileData & (BLOCKED_1_EAST | BLOCKED_2_EAST)) != 0) {
g.drawString("Can not walk east", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_EAST | BLOCKED_2_EAST);
}
if ((newTileData & (BLOCKED_1_SOUTH | BLOCKED_2_SOUTH)) != 0) {
g.drawString("Can not walk south", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_SOUTH | BLOCKED_2_SOUTH);
}
if ((newTileData & (BLOCKED_1_SOUTH_EAST | BLOCKED_2_SOUTH_EAST)) != 0) {
g.drawString("Can not walk south east", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_SOUTH_EAST | BLOCKED_2_SOUTH_EAST);
}
if ((newTileData & (BLOCKED_1_SOUTH_WEST | BLOCKED_2_WEST)) != 0) {
g.drawString("Can not walk south west", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_SOUTH_WEST | BLOCKED_2_SOUTH_WEST);
}
if ((newTileData & (BLOCKED_1_WEST | BLOCKED_2_WEST)) != 0) {
g.drawString("Can not walk west", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_WEST | BLOCKED_2_WEST);
}
if ((newTileData & (BLOCKED_1_NORTH_WEST | BLOCKED_2_NORTH_WEST)) != 0) {
g.drawString("Can not walk west", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (BLOCKED_1_NORTH_WEST | BLOCKED_2_NORTH_WEST);
}
if ((newTileData & (FULL_BLOCK)) != 0) {
g.drawString("Tile is blocked", 20, 140 + 20 * flagNum);
flagNum++;
newTileData = newTileData ^ (FULL_BLOCK);
}
int pos = 0;
binaryTileData = Integer.toString(newTileData, 2);
for (int i = binaryTileData.length() - 1; i >= 0; i--, pos++) {
char c = binaryTileData.charAt(i);
if (c != '1') {
continue;
}
int hex = 1 << pos;
g.drawString("Flag" + pos + "(0x" + Integer.toString(hex, 16) + ") is true", 20, 140 + 20 * flagNum);
flagNum++;
}
} catch (Throwable throwable) {
g.drawString(throwable.getMessage(), 20, 100);
}
}
}