int RADIUS_XZ = 3;
int RADIUS_Y = 2;
double REACH = 4.5;
double REACH_SQ = REACH * REACH;
String[] FACES = new String[]{ "UP", "DOWN", "NORTH", "SOUTH", "WEST", "EAST" };
int[] DX = new int[]{ 0, 0, 0, 0,-1, 1 };
int[] DY = new int[]{ 1,-1, 0, 0, 0, 0 };
int[] DZ = new int[]{ 0, 0,-1, 1, 0, 0 };
float lastYaw = 0f;
float lastPitch = 0f;
boolean hasLastRot = false;
int baseX;
int baseY;
int baseZ;
String targetFace;
@Module(name="Scaffold2", category="MOVE", description="Simple Scaffold", defaultEnabled=false)
void meta(valueManager) {
valueManager.registerSliderDouble("rotation_speed", "Rotation Speed", 30.0, 180.0, 180.0, 5.0);
valueManager.registerBoolean("move_fix", "Move Fix", true);
valueManager.registerBoolean("keep_rotation", "Keep Rotation", true);
}
@EventTarget(events="player_update")
void onPlayerUpdate(event) {
player = me.getPlayer();
if (player == null) return;
double rotationSpeed = me.getNumber("rotation_speed");
boolean moveFix = me.getBool("move_fix");
boolean keepRotation = me.getBool("keep_rotation");
if (findTarget(player)) {
int blockSlot = findBlockSlot();
if (blockSlot < 0) {
moduleManager.self().disable();
return;
}
int currentSlot = inventory.getSlot();
boolean didSwitch = (blockSlot != currentSlot);
if (didSwitch) inventory.switchTo(blockSlot);
double[] hit = faceCenter(baseX, baseY, baseZ, targetFace);
float[] rot = me.getRotation(hit[0], hit[1], hit[2]);
me.setRotation(rot[0], rot[1], (float) rotationSpeed, moveFix);
me.placeBlock(baseX, baseY, baseZ, targetFace, "MAIN_HAND");
lastYaw = rot[0];
lastPitch = rot[1];
hasLastRot = true;
} else if (keepRotation && hasLastRot) {
me.setRotation(lastYaw, lastPitch, (float) rotationSpeed, moveFix);
}
}
int findBlockSlot() {
int cur = inventory.getSlot();
if (cur >= 0 && cur < 9) {
cs = inventory.getStackInSlot(cur);
if (cs != null && !cs.isEmpty() && cs.isBlock()) return cur;
}
for (int i = 0; i < 9; i++) {
s = inventory.getStackInSlot(i);
if (s != null && !s.isEmpty() && s.isBlock()) return i;
}
return -1;
}
boolean findTarget(player) {
world = me.getWorld();
if (world == null) return false;
pos = player.getPosition();
int tx = (int) Math.floor(pos.x);
int ty = (int) Math.floor(pos.y) - 1;
int tz = (int) Math.floor(pos.z);
if (!world.isReplaceable(tx, ty, tz)) return false;
double tcx = tx + 0.5;
double tcy = ty + 0.5;
double tcz = tz + 0.5;
double bestDistSq = Double.MAX_VALUE;
boolean found = false;
for (int dx = -RADIUS_XZ; dx <= RADIUS_XZ; dx++) {
for (int dy = -RADIUS_Y; dy <= 0; dy++) {
for (int dz = -RADIUS_XZ; dz <= RADIUS_XZ; dz++) {
int cx = tx + dx;
int cy = ty + dy;
int cz = tz + dz;
if (world.isReplaceable(cx, cy, cz)) continue;
if (world.isInteractable(cx, cy, cz)) continue;
double pcx = cx + 0.5 - pos.x;
double pcy = cy + 0.5 - pos.y;
double pcz = cz + 0.5 - pos.z;
if (pcx * pcx + pcy * pcy + pcz * pcz > REACH_SQ) continue;
int bestFaceIdx = pickBestFace(cx, cy, cz, tx, ty, tz, world);
if (bestFaceIdx < 0) continue;
double ddx = cx + 0.5 - tcx;
double ddy = cy + 0.5 - tcy;
double ddz = cz + 0.5 - tcz;
double distSq = ddx * ddx + ddy * ddy + ddz * ddz;
if (distSq < bestDistSq) {
bestDistSq = distSq;
baseX = cx;
baseY = cy;
baseZ = cz;
targetFace = FACES[bestFaceIdx];
found = true;
}
}
}
}
return found;
}
int pickBestFace(int cx, int cy, int cz, int tx, int ty, int tz, world) {
int best = -1;
double bestD = Double.MAX_VALUE;
double tcx = tx + 0.5;
double tcy = ty + 0.5;
double tcz = tz + 0.5;
for (int i = 0; i < 6; i++) {
if ("DOWN".equals(FACES[i])) continue;
int nx = cx + DX[i];
int ny = cy + DY[i];
int nz = cz + DZ[i];
if (!world.isReplaceable(nx, ny, nz)) continue;
double ex = nx + 0.5 - tcx;
double ey = ny + 0.5 - tcy;
double ez = nz + 0.5 - tcz;
double d = ex * ex + ey * ey + ez * ez;
if (d < bestD) {
bestD = d;
best = i;
}
}
return best;
}
double[] faceCenter(int x, int y, int z, String face) {
double cx = x + 0.5;
double cy = y + 0.5;
double cz = z + 0.5;
if ("UP".equals(face)) cy = y + 1.0;
if ("DOWN".equals(face)) cy = y;
if ("NORTH".equals(face)) cz = z;
if ("SOUTH".equals(face)) cz = z + 1.0;
if ("WEST".equals(face)) cx = x;
if ("EAST".equals(face)) cx = x + 1.0;
return new double[]{ cx, cy, cz };
}
@OnEnable
void onEnable() {
hasLastRot = false; me.chat("§a[Scaffold2] on§r");
}
@OnDisable
void onDisable() {
inventory.switchBack();
me.chat("§c[Scaffold2] off§r");
}