我正在创建一个自定义的反作弊。然而,我已经到了一个让我很困惑的地步。我试图检测玩家是否可以在所述位置放置块,但随着我试图使其对非作弊玩家更可靠,它变得越来越复杂。目前,每当玩家与AxisAllignedBB
块(我相信,问题在于玩家的方向每秒只更新 20 次,而他们的帧速率可能会高得多。这通常会导致(在我的测试中大约每 15 个左右的块位置一次)被错误地取消。PlayerInteractEvent
Block
BlockFace
PlayerInteractEvent
用于查找 Block 的 Raycast 算法
public static Block getTargetBlock(Location location, Vector direction, double rangeSquared, int maxTrials, TargetMethod targetMethod) {
Location loc = location.clone();
Vector dir = direction.normalize();
final double directionX = direction.getX();
final double directionY = direction.getY();
final double directionZ = direction.getZ();
Block block = loc.getBlock();
for (int i = 0; i <= maxTrials; i++) {
final double locX = loc.getX();
final double locY = loc.getY();
final double locZ = loc.getZ();
double wholeMoreX = wholeMore(locX,directionX);
double moreX = Math.abs(wholeMoreX /directionX);
double wholeMoreY = wholeMore(locY,directionY);
double moreY = Math.abs(wholeMoreY /directionY);
double wholeMoreZ = wholeMore(locZ,directionZ);
double moreZ = Math.abs(wholeMoreZ /directionZ);
if(moreX < moreY && moreX < moreZ){
if(directionX > 0)
block = block.getRelative(BlockFace.EAST);
else {
block = block.getRelative(BlockFace.WEST);
}
}
else if(moreY < moreX && moreY < moreZ){
if(directionY > 0){
block = block.getRelative(BlockFace.UP);
}
else{
block = block.getRelative(BlockFace.DOWN);
}
}
else{
if(directionZ > 0){
block = block.getRelative(BlockFace.SOUTH);
}
else{
block = block.getRelative(BlockFace.NORTH);
}
}
final double scalar = Math.min(Math.min(moreX,moreY),moreZ);
Vector addAmount = dir.clone().multiply(scalar);
loc.add(addAmount);
if(loc.distanceSquared(location) > rangeSquared)
return null;
AxisAlignedBB boundry = getBoundry(block,targetMethod);
if(boundry != null)
if(blockFaceCollide(location,direction,boundry) != null)
return block;
}
return null;
}
但是,我怀疑这是问题所在。根据我的测试,它工作得很好。因此,我认为我必须依靠替代方法。这里有一些想法,但我不太确定它们是否令人满意。
想法:靠近街区
我考虑过放置的块是否在从光线投射中找到的块的 1 个块半径内(或者如果我正在查看与光线的块的最近距离,则可能更短),但这会带来太多问题。如果玩家将光标从障碍物移到更远的区域,则会触发作弊的误报。另一方面,玩家仍然可以在完全封闭的区域内建造,如果他们有北、东、南、西而不是西北、东北等的柱子。
想法:A* 寻路算法
如果我在 raycast 中将光线上的点设置为 0 G-Cost,G-Cost 会随着与光线的距离而增加,而 H-Cost 是距离目标块最近的距离,我觉得这可以解决这个难题。PlayerInteractEvent
我可以在取消之前设置一个最大 G-Cost 阈值。然而,问题是将 A* 与块的各种 AxisAllignedBB 结合起来似乎很困难。我也许可以创建一个由每个块 100x100x100 个点组成的网格,但我不确定这是否有效,也不是最佳实践。
思路:看看玩家能不能看到方块
这将非常有效,但我不确定它是否现实。为此,每次玩家放置一个块时,我都需要检测哪些块会与玩家交互半径中的其他块完全重叠。取出所有最终的非重叠块,我可以查看交互块是否包含这些。否则,交互将被取消。这似乎可能会对性能造成影响,而且我可以看到作弊也可能存在一些误报。