Skip to content
This repository has been archived by the owner on Jun 28, 2024. It is now read-only.

Commit

Permalink
Block tracker Jank: Introducing "Script Kiddie Multithreading"
Browse files Browse the repository at this point in the history
  • Loading branch information
TacoTechnica committed Jan 23, 2022
1 parent ba3f508 commit 6d2a6b2
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/main/java/adris/altoclef/AltoClef.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,9 @@ public void onClientTick() {
_miscBlockTracker.tick();

_trackerManager.tick();
_blockTracker.preTickTask();
_taskRunner.tick();
_blockTracker.postTickTask();

_butler.tick();
_messageSender.tick();
Expand Down
47 changes: 42 additions & 5 deletions src/main/java/adris/altoclef/trackers/BlockTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import net.minecraft.util.math.Vec3d;

import java.util.*;
import java.util.concurrent.Semaphore;
import java.util.function.Predicate;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -52,12 +53,18 @@ public class BlockTracker extends Tracker {

private final TimerGame _forceElapseTimer = new TimerGame(_config.scanIntervalWhenNewBlocksFound);

// A scan can last no more than 15 seconds
private final TimerGame _asyncForceResetScanFlag = new TimerGame(15);

private final Map<Block, Integer> _trackingBlocks = new HashMap<>();

private final Object _scanMutex = new Object();

private boolean _scanning = false;

// Only perform scans at the END of our frame
private final Semaphore _endOfFrameMutex = new Semaphore(1);

//private Block _currentlyTracking = null;
private final AltoClef _mod;

Expand All @@ -76,6 +83,19 @@ protected void updateState() {
}
}

// We want our `_trackingBlocks` value to be read AFTER tasks have finished ticking
public void preTickTask() {
try {
_endOfFrameMutex.acquire();
} catch (InterruptedException e) {
Debug.logWarning("Pre-tick failed to acquire block track mutex! (send logs)");
e.printStackTrace();
}
}
public void postTickTask() {
_endOfFrameMutex.release();
}

@Override
protected void reset() {
// Tasks will handle de-tracking blocks.
Expand Down Expand Up @@ -280,21 +300,38 @@ private void update() {
_timer.setInterval(_config.scanInterval);
CalculationContext ctx = new CalculationContext(_mod.getClientBaritone(), _config.scanAsynchronously);
if (_config.scanAsynchronously) {
if (_scanning && _asyncForceResetScanFlag.elapsed()) {
Debug.logMessage("SCANNING TOOK TOO LONG! Will assume it ended mid way. Hopefully this won't break anything...");
_scanning = false;
}
if (!_scanning) {
_scanning = true;
Baritone.getExecutor().execute(() -> {
rescanWorld(ctx);
_scanning = true;
_asyncForceResetScanFlag.reset();
rescanWorld(ctx, true);
_scanning = false;
});
}
} else {
// Synchronous scanning.
rescanWorld(ctx);
rescanWorld(ctx, false);
}
}

private void rescanWorld(CalculationContext ctx) {
private void rescanWorld(CalculationContext ctx, boolean async) {
Block[] blocksToScan;
if (async) {
// Wait for end of frame
try {
_endOfFrameMutex.acquire();
_endOfFrameMutex.release();
} catch (InterruptedException e) {
Debug.logWarning("RESCAN INTERRUPTED! Will SKIP the scan (see logs)");
_endOfFrameMutex.release();
e.printStackTrace();
return;
}
}
synchronized (_trackingBlocks) {
Debug.logInternal("Rescanning world for " + _trackingBlocks.size() + " blocks... Hopefully not dummy slow.");
blocksToScan = new Block[_trackingBlocks.size()];
Expand All @@ -318,7 +355,7 @@ private void rescanWorld(CalculationContext ctx) {

// The scanning may run asynchronously.
BlockOptionalMetaLookup boml = new BlockOptionalMetaLookup(blocksToScan);
List<BlockPos> found = MineProcess.searchWorld(ctx, boml, 64, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
List<BlockPos> found = MineProcess.searchWorld(ctx, boml, _config.maxCacheSizePerBlockType, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());

synchronized (_scanMutex) {
if (MinecraftClient.getInstance().world != null) {
Expand Down

0 comments on commit 6d2a6b2

Please sign in to comment.