Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/com/github/manolo8/darkbot/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

public class Main extends Thread implements PluginListener, BotAPI {

public static final Version VERSION = new Version("1.13.17 beta 105 alpha 1");
public static final Version VERSION = new Version("1.13.17 beta 106 alpha 1");
public static final Object UPDATE_LOCKER = new Object();
public static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
Expand Down
23 changes: 22 additions & 1 deletion src/main/java/com/github/manolo8/darkbot/core/IDarkBotAPI.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.github.manolo8.darkbot.core;

import com.github.manolo8.darkbot.core.api.GameAPI;

import com.github.manolo8.darkbot.core.api.util.DataBuffer;
import eu.darkbot.api.game.other.Locatable;
import eu.darkbot.api.managers.MemoryAPI;
import eu.darkbot.api.managers.OreAPI;
import eu.darkbot.api.managers.WindowAPI;

import java.util.function.Consumer;
import java.util.function.Predicate;

public interface IDarkBotAPI extends WindowAPI, MemoryAPI {
Expand Down Expand Up @@ -85,6 +86,26 @@ default void readMemory(long address, byte[] buffer) {
}
void readMemory(long address, byte[] buffer, int length);

/**
* Reads data at given address, use always with try-with-resources
* Length limit is {@link DataBuffer#MAX_CHUNK_SIZE}
*
* @param address to read
* @param length the length of the data to read
* @return {@link DataBuffer}
*/
DataBuffer readData(long address, int length);

/**
* Length limit is {@link DataBuffer#MAX_CHUNK_SIZE}
*
* @param address to read
* @param length the length of the data to read
* @param reader consumer which will be used if read was success
* @return false if read failed, true otherwise
*/
boolean readData(long address, int length, Consumer<DataBuffer> reader);

void writeMemoryInt(long address, int value);
void writeMemoryLong(long address, long value);
void writeMemoryDouble(long address, double value);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.manolo8.darkbot.core.api;

import com.github.manolo8.darkbot.core.api.util.ByteBufferReader;
import com.github.manolo8.darkbot.core.api.util.DataReader;
import com.github.manolo8.darkbot.core.BotInstaller;
import com.github.manolo8.darkbot.core.utils.ByteUtils;
import com.github.manolo8.darkbot.utils.StartupParams;
Expand Down Expand Up @@ -46,4 +48,39 @@ public void setMaxFps(int maxFps) {
}
}

@Override
protected DataReader createReader(int idx) {
if (window.getVersion() >= 9)
return new DarkBoatByteBufferReader(idx, memory, extraMemoryReader);

return super.createReader(idx);
}

static class DarkBoatByteBufferReader extends ByteBufferReader implements DataReader {

private final int idx;
private final DarkBoat darkBoat;

public DarkBoatByteBufferReader(int idx, DarkBoat darkBoat, GameAPI.ExtraMemoryReader reader) {
super(darkBoat.getBuffer(idx), reader);
this.idx = idx;
this.darkBoat = darkBoat;
}

@Override
public Result read(long address, int length) {
if (!inUse.compareAndSet(false, true)) return DataReader.Result.BUSY;

boolean res = darkBoat.readToBuffer(idx, address, length);
if (!res) return Result.ERROR;

reset(length);
return Result.OK;
}

@Override
public byte[] toArray() {
return getArray(new byte[getAvailable()], 0, getAvailable());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.manolo8.darkbot.core.api;

import com.github.manolo8.darkbot.core.api.util.DataReader;
import com.github.manolo8.darkbot.core.BotInstaller;
import com.github.manolo8.darkbot.core.manager.HookAdapter;
import com.github.manolo8.darkbot.core.utils.ByteUtils;
Expand Down Expand Up @@ -52,4 +53,11 @@ public boolean hasCapability(GameAPI.Capability capability) {
return super.hasCapability(capability);
}

@Override
protected DataReader createReader(int idx) {
if (window.getVersion() >= 9)
return new DarkBoatAdapter.DarkBoatByteBufferReader(idx, memory, extraMemoryReader);

return super.createReader(idx);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.github.manolo8.darkbot.core.api;

import com.github.manolo8.darkbot.core.IDarkBotAPI;
import com.github.manolo8.darkbot.core.api.util.DataBuffer;
import com.github.manolo8.darkbot.core.api.util.DataReader;
import com.github.manolo8.darkbot.core.api.util.DefaultByteBufferReader;
import com.github.manolo8.darkbot.core.manager.HeroManager;
import com.github.manolo8.darkbot.gui.utils.PidSelector;
import com.github.manolo8.darkbot.gui.utils.Popups;
Expand Down Expand Up @@ -42,7 +45,8 @@ public class GameAPIImpl<

protected final String version;

private final Consumer<Integer> fpsLimitListener; // Needs to be kept as a strong reference to avoid GC
@SuppressWarnings("FieldCanBeLocal") // Needs to be kept as a strong reference to avoid GC
private final Consumer<Integer> fpsLimitListener;

protected final LoginData loginData; // Used only if api supports LOGIN
protected int pid; // Used only if api supports ATTACH
Expand All @@ -51,6 +55,8 @@ public class GameAPIImpl<

protected long lastFailedLogin;

protected DataReader[] dataReaders = new DataReader[10];

public GameAPIImpl(StartupParams params,
W window, H handler, M memory, E extraMemoryReader, I interaction, D direct,
GameAPI.Capability... capabilityArr) {
Expand Down Expand Up @@ -279,6 +285,41 @@ public void readMemory(long address, byte[] buffer, int length) {
memory.readBytes(address, buffer, length);
}

@Override
public DataBuffer readData(long address, int length) throws RuntimeException {
if (length <= 0 || length > DataBuffer.MAX_CHUNK_SIZE)
throw new ArrayIndexOutOfBoundsException("Length is <= 0 or exceeds max chunk size: " + DataBuffer.MAX_CHUNK_SIZE);

for (int i = 0; i < dataReaders.length; i++) {
DataReader reader = dataReaders[i];
if (reader == null) reader = (dataReaders[i] = createReader(i));

switch (reader.read(address, length)) {
case BUSY: continue;
case ERROR:
reader.reset(0);
case OK:
return reader;
}
}

throw new RuntimeException("All DataReaders are in use. Some code is calling readData and not closing the resource!");
}

@Override
public boolean readData(long address, int length, Consumer<DataBuffer> reader) {
try (DataBuffer r = readData(address, length)) {
if (r.getLimit() != length) return false;

reader.accept(r);
}
return true;
}

protected DataReader createReader(int idx) {
return DefaultByteBufferReader.of(memory, extraMemoryReader);
}

@Override
public void replaceInt(long address, int oldValue, int newValue) {
memory.replaceInt(address, oldValue, newValue);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package com.github.manolo8.darkbot.core.api.util;

import com.github.manolo8.darkbot.core.api.GameAPI;
import com.github.manolo8.darkbot.core.utils.ByteUtils;

import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Generic DataReader implementation backed by a byte buffer.
* May be extended to provide reading in different ways.
*/
public class ByteBufferReader implements DataBuffer {

protected final ByteBuffer buffer;
protected final GameAPI.ExtraMemoryReader reader;

protected final AtomicBoolean inUse = new AtomicBoolean();

public ByteBufferReader(ByteBuffer buffer, GameAPI.ExtraMemoryReader reader) {
this.buffer = buffer;
this.reader = reader;
}

public ByteBuffer getByteBuffer() {
return buffer;
}

public void reset(int limit) {
buffer.clear();
buffer.limit(limit);
}

@Override
public int getPosition() {
return buffer.position();
}

@Override
public void setPosition(int pos) {
buffer.position(pos);
}

@Override
public int getLimit() {
return buffer.limit();
}

@Override
public int getAvailable() {
return buffer.remaining();
}

@Override
public byte getByte() {
return buffer.get();
}

@Override
public byte getByte(int idx) {
return buffer.get(idx);
}

@Override
public boolean getBoolean() {
return getInt() == 1;
}

@Override
public boolean getBoolean(int idx) {
return getByte(idx) == 1;
}

@Override
public short getShort() {
return buffer.getShort();
}

@Override
public short getShort(int idx) {
return buffer.getShort(idx);
}

@Override
public int getInt() {
return buffer.getInt();
}

@Override
public int getInt(int idx) {
return buffer.getInt(idx);
}

@Override
public long getLong() {
return buffer.getLong();
}

@Override
public long getLong(int idx) {
return buffer.getLong(idx);
}

@Override
public long getPointer() {
return buffer.getLong() & ByteUtils.ATOM_MASK;
}

@Override
public long getPointer(int idx) {
return buffer.getLong(idx) & ByteUtils.ATOM_MASK;
}

@Override
public double getDouble() {
return buffer.getDouble();
}

@Override
public double getDouble(int idx) {
return buffer.getDouble(idx);
}

@Override
public String getString() {
return reader.readString(getLong());
}

@Override
public String getString(int idx) {
return reader.readString(getLong(idx));
}

@Override
public byte[] toArray() {
return buffer.array();
}

@Override
public byte[] getArray(byte[] dst, int offset, int length) {
buffer.get(dst, offset, length);
return dst;
}

@Override
public void close() {
inUse.set(false);
}
}
Loading