mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-04 03:10:27 +02:00
Spaces/comment.
This commit is contained in:
parent
a5d6594591
commit
0973149f0f
|
@ -34,33 +34,33 @@ import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||||
* @see BlockPlaceEvent
|
* @see BlockPlaceEvent
|
||||||
*/
|
*/
|
||||||
public class BlockPlaceListener extends CheckListener {
|
public class BlockPlaceListener extends CheckListener {
|
||||||
|
|
||||||
private static final int p1 = 73856093;
|
|
||||||
private static final int p2 = 19349663;
|
|
||||||
private static final int p3 = 83492791;
|
|
||||||
|
|
||||||
private static final int getHash(final int x, final int y, final int z) {
|
private static final int p1 = 73856093;
|
||||||
return p1 * x ^ p2 * y ^ p3 * z;
|
private static final int p2 = 19349663;
|
||||||
}
|
private static final int p3 = 83492791;
|
||||||
|
|
||||||
public static int getCoordHash(final Block block){
|
private static final int getHash(final int x, final int y, final int z) {
|
||||||
return getHash(block.getX(), block.getY(), block.getZ());
|
return p1 * x ^ p2 * y ^ p3 * z;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getBlockPlaceHash(final Block block, final Material mat){
|
public static int getCoordHash(final Block block){
|
||||||
int hash = getCoordHash(block);
|
return getHash(block.getX(), block.getY(), block.getZ());
|
||||||
if (mat != null){
|
}
|
||||||
hash |= mat.name().hashCode();
|
|
||||||
}
|
public static int getBlockPlaceHash(final Block block, final Material mat){
|
||||||
hash |= block.getWorld().getName().hashCode();
|
int hash = getCoordHash(block);
|
||||||
return hash;
|
if (mat != null){
|
||||||
}
|
hash |= mat.name().hashCode();
|
||||||
|
}
|
||||||
/** Against. */
|
hash |= block.getWorld().getName().hashCode();
|
||||||
private final Against against = addCheck(new Against());
|
return hash;
|
||||||
|
}
|
||||||
/** AutoSign. */
|
|
||||||
private final AutoSign autoSign = addCheck(new AutoSign());
|
/** Against. */
|
||||||
|
private final Against against = addCheck(new Against());
|
||||||
|
|
||||||
|
/** AutoSign. */
|
||||||
|
private final AutoSign autoSign = addCheck(new AutoSign());
|
||||||
|
|
||||||
/** The direction check. */
|
/** The direction check. */
|
||||||
private final Direction direction = addCheck(new Direction());
|
private final Direction direction = addCheck(new Direction());
|
||||||
|
@ -76,16 +76,16 @@ public class BlockPlaceListener extends CheckListener {
|
||||||
|
|
||||||
/** The speed check. */
|
/** The speed check. */
|
||||||
private final Speed speed = addCheck(new Speed());
|
private final Speed speed = addCheck(new Speed());
|
||||||
|
|
||||||
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
|
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
|
||||||
private final Location useLoc = new Location(null, 0, 0, 0);
|
private final Location useLoc = new Location(null, 0, 0, 0);
|
||||||
|
|
||||||
private final Counters counters = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(Counters.class);
|
private final Counters counters = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(Counters.class);
|
||||||
private final int idBoatsAnywhere = counters.registerKey("boatsanywhere");
|
private final int idBoatsAnywhere = counters.registerKey("boatsanywhere");
|
||||||
private final int idEnderPearl = counters.registerKey("throwenderpearl");
|
private final int idEnderPearl = counters.registerKey("throwenderpearl");
|
||||||
|
|
||||||
public BlockPlaceListener(){
|
public BlockPlaceListener(){
|
||||||
super(CheckType.BLOCKPLACE);
|
super(CheckType.BLOCKPLACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,85 +97,85 @@ public class BlockPlaceListener extends CheckListener {
|
||||||
@EventHandler(
|
@EventHandler(
|
||||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onBlockPlace(final BlockPlaceEvent event) {
|
public void onBlockPlace(final BlockPlaceEvent event) {
|
||||||
|
|
||||||
final Block block = event.getBlockPlaced();
|
final Block block = event.getBlockPlaced();
|
||||||
final Block blockAgainst = event.getBlockAgainst();
|
final Block blockAgainst = event.getBlockAgainst();
|
||||||
// Skip any null blocks.
|
// Skip any null blocks.
|
||||||
if (block == null || blockAgainst == null)
|
if (block == null || blockAgainst == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: Revise material use (not block.get... ?)
|
// TODO: Revise material use (not block.get... ?)
|
||||||
//final Material mat = block.getType();
|
//final Material mat = block.getType();
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
final Material placedMat = player.getItemInHand().getType(); // Safety first.
|
final Material placedMat = player.getItemInHand().getType(); // Safety first.
|
||||||
boolean cancelled = false;
|
boolean cancelled = false;
|
||||||
|
|
||||||
final BlockPlaceData data = BlockPlaceData.getData(player);
|
final BlockPlaceData data = BlockPlaceData.getData(player);
|
||||||
final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player);
|
final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player);
|
||||||
|
|
||||||
if (placedMat == Material.SIGN){
|
if (placedMat == Material.SIGN){
|
||||||
// Might move to MONITOR priority.
|
// Might move to MONITOR priority.
|
||||||
data.autoSignPlacedTime = System.currentTimeMillis();
|
data.autoSignPlacedTime = System.currentTimeMillis();
|
||||||
// Always hash as sign post for improved compatibility with Lockette etc.
|
// Always hash as sign post for improved compatibility with Lockette etc.
|
||||||
data.autoSignPlacedHash = getBlockPlaceHash(block, Material.SIGN);
|
data.autoSignPlacedHash = getBlockPlaceHash(block, Material.SIGN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast place check.
|
// Fast place check.
|
||||||
if (fastPlace.isEnabled(player)){
|
if (fastPlace.isEnabled(player)){
|
||||||
if (fastPlace.check(player, block, data, cc)) {
|
if (fastPlace.check(player, block, data, cc)) {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
} else {
|
} else {
|
||||||
// Feed the improbable.
|
// Feed the improbable.
|
||||||
Improbable.feed(player, 0.5f, System.currentTimeMillis());
|
Improbable.feed(player, 0.5f, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No swing check (player doesn't swing their arm when placing a lily pad).
|
// No swing check (player doesn't swing their arm when placing a lily pad).
|
||||||
if (!cancelled && !cc.noSwingExceptions.contains(placedMat) && noSwing.isEnabled(player) && noSwing.check(player, data, cc)) {
|
if (!cancelled && !cc.noSwingExceptions.contains(placedMat) && noSwing.isEnabled(player) && noSwing.check(player, data, cc)) {
|
||||||
// Consider skipping all insta placables or using simplified version (true or true within time frame).
|
// Consider skipping all insta placables or using simplified version (true or true within time frame).
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reach check (distance).
|
// Reach check (distance).
|
||||||
if (!cancelled && reach.isEnabled(player) && reach.check(player, block, data, cc)) {
|
if (!cancelled && reach.isEnabled(player) && reach.check(player, block, data, cc)) {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direction check.
|
// Direction check.
|
||||||
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, blockAgainst, data, cc)) {
|
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, blockAgainst, data, cc)) {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Surrounding material.
|
// Surrounding material.
|
||||||
if (!cancelled && against.isEnabled(player) && against.check(player, block, placedMat, blockAgainst, data, cc)) {
|
if (!cancelled && against.isEnabled(player) && against.check(player, block, placedMat, blockAgainst, data, cc)) {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If one of the checks requested to cancel the event, do so.
|
// If one of the checks requested to cancel the event, do so.
|
||||||
if (cancelled) {
|
if (cancelled) {
|
||||||
event.setCancelled(cancelled);
|
event.setCancelled(cancelled);
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
// Reminder(currently unused): useLoc.setWorld(null);
|
// Reminder(currently unused): useLoc.setWorld(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||||
public void onSignChange(final SignChangeEvent event){
|
public void onSignChange(final SignChangeEvent event){
|
||||||
if (event.getClass() != SignChangeEvent.class){
|
if (event.getClass() != SignChangeEvent.class){
|
||||||
// Built in plugin compatibility.
|
// Built in plugin compatibility.
|
||||||
// TODO: Don't understand why two consecutive events editing the same block are a problem.
|
// TODO: Don't understand why two consecutive events editing the same block are a problem.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
final Block block = event.getBlock();
|
final Block block = event.getBlock();
|
||||||
final String[] lines = event.getLines();
|
final String[] lines = event.getLines();
|
||||||
if (block == null || lines == null || player == null){
|
if (block == null || lines == null || player == null){
|
||||||
// Somewhat defensive.
|
// Somewhat defensive.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (autoSign.isEnabled(player) && autoSign.check(player, block, lines)){
|
if (autoSign.isEnabled(player) && autoSign.check(player, block, lines)){
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -201,41 +201,41 @@ public class BlockPlaceListener extends CheckListener {
|
||||||
@EventHandler(
|
@EventHandler(
|
||||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onPlayerInteract(final PlayerInteractEvent event) {
|
public void onPlayerInteract(final PlayerInteractEvent event) {
|
||||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
|
|
||||||
final ItemStack stack = player.getItemInHand();
|
final ItemStack stack = player.getItemInHand();
|
||||||
if (stack == null) return;
|
if (stack == null) return;
|
||||||
|
|
||||||
final Material type = stack.getType();
|
final Material type = stack.getType();
|
||||||
|
|
||||||
if (type == Material.BOAT){
|
if (type == Material.BOAT){
|
||||||
// Check boats-anywhere.
|
// Check boats-anywhere.
|
||||||
final org.bukkit.block.Block block = event.getClickedBlock();
|
final org.bukkit.block.Block block = event.getClickedBlock();
|
||||||
final Material mat = block.getType();
|
final Material mat = block.getType();
|
||||||
|
|
||||||
// TODO: allow lava ?
|
// TODO: allow lava ?
|
||||||
if (mat == Material.WATER || mat == Material.STATIONARY_WATER) return;
|
if (mat == Material.WATER || mat == Material.STATIONARY_WATER) return;
|
||||||
|
|
||||||
final org.bukkit.block.Block relBlock = block.getRelative(event.getBlockFace());
|
final org.bukkit.block.Block relBlock = block.getRelative(event.getBlockFace());
|
||||||
final Material relMat = relBlock.getType();
|
final Material relMat = relBlock.getType();
|
||||||
|
|
||||||
// TODO: Placing inside of water, but not "against" ?
|
// TODO: Placing inside of water, but not "against" ?
|
||||||
if (relMat == Material.WATER || relMat == Material.STATIONARY_WATER) return;
|
if (relMat == Material.WATER || relMat == Material.STATIONARY_WATER) return;
|
||||||
|
|
||||||
if (!player.hasPermission(Permissions.BLOCKPLACE_BOATSANYWHERE)){
|
if (!player.hasPermission(Permissions.BLOCKPLACE_BOATSANYWHERE)){
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
counters.addPrimaryThread(idBoatsAnywhere, 1);
|
counters.addPrimaryThread(idBoatsAnywhere, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (type == Material.MONSTER_EGG){
|
else if (type == Material.MONSTER_EGG){
|
||||||
// Check blockplace.speed.
|
// Check blockplace.speed.
|
||||||
if (speed.isEnabled(player) && speed.check(player)) {
|
if (speed.isEnabled(player) && speed.check(player)) {
|
||||||
// If the check was positive, cancel the event.
|
// If the check was positive, cancel the event.
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,29 +248,29 @@ public class BlockPlaceListener extends CheckListener {
|
||||||
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onProjectileLaunch(final ProjectileLaunchEvent event) {
|
public void onProjectileLaunch(final ProjectileLaunchEvent event) {
|
||||||
// The shooter needs to be a player.
|
// The shooter needs to be a player.
|
||||||
final Projectile projectile = event.getEntity();
|
final Projectile projectile = event.getEntity();
|
||||||
final Player player = BridgeMisc.getShooterPlayer(projectile);
|
final Player player = BridgeMisc.getShooterPlayer(projectile);
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// And the projectile must be one the following:
|
// And the projectile must be one the following:
|
||||||
EntityType type = event.getEntityType();
|
EntityType type = event.getEntityType();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ENDER_PEARL:
|
case ENDER_PEARL:
|
||||||
break;
|
break;
|
||||||
case ENDER_SIGNAL:
|
case ENDER_SIGNAL:
|
||||||
break;
|
break;
|
||||||
case EGG:
|
case EGG:
|
||||||
break;
|
break;
|
||||||
case SNOWBALL:
|
case SNOWBALL:
|
||||||
break;
|
break;
|
||||||
case THROWN_EXP_BOTTLE:
|
case THROWN_EXP_BOTTLE:
|
||||||
break;
|
break;
|
||||||
case SPLASH_POTION:
|
case SPLASH_POTION:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the actual check...
|
// Do the actual check...
|
||||||
|
@ -279,56 +279,56 @@ public class BlockPlaceListener extends CheckListener {
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
final Location loc = player.getLocation(useLoc);
|
final Location loc = player.getLocation(useLoc);
|
||||||
if (Combined.checkYawRate(player, loc.getYaw(), now, loc.getWorld().getName())){
|
if (Combined.checkYawRate(player, loc.getYaw(), now, loc.getWorld().getName())){
|
||||||
// Yawrate (checked extra).
|
// Yawrate (checked extra).
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
if (speed.check(player)){
|
if (speed.check(player)){
|
||||||
// If the check was positive, cancel the event.
|
// If the check was positive, cancel the event.
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
else if (Improbable.check(player, 0.6f, now, "blockplace.speed")){
|
else if (Improbable.check(player, 0.6f, now, "blockplace.speed")){
|
||||||
// Combined fighting speed.
|
// Combined fighting speed.
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ender pearl glitch (ab-) use.
|
// Ender pearl glitch (ab-) use.
|
||||||
if (!cancel && type == EntityType.ENDER_PEARL){
|
if (!cancel && type == EntityType.ENDER_PEARL){
|
||||||
if (!CombinedConfig.getConfig(player).enderPearlCheck){
|
if (!CombinedConfig.getConfig(player).enderPearlCheck){
|
||||||
// Do nothing !
|
// Do nothing !
|
||||||
// TODO: Might have further flags?
|
// TODO: Might have further flags?
|
||||||
}
|
}
|
||||||
else if (!BlockProperties.isPassable(projectile.getLocation(useLoc))){
|
else if (!BlockProperties.isPassable(projectile.getLocation(useLoc))){
|
||||||
// Launch into a block.
|
// Launch into a block.
|
||||||
// TODO: This might be a general check later.
|
// TODO: This might be a general check later.
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (!BlockProperties.isPassable(player.getEyeLocation(), projectile.getLocation(useLoc))){
|
if (!BlockProperties.isPassable(player.getEyeLocation(), projectile.getLocation(useLoc))){
|
||||||
// (Spare a useLoc2, for this is seldom rather.)
|
// (Spare a useLoc2, for this is seldom rather.)
|
||||||
// Something between player
|
// Something between player
|
||||||
// TODO: This might be a general check later.
|
// TODO: This might be a general check later.
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
final Material mat = player.getLocation(useLoc).getBlock().getType();
|
final Material mat = player.getLocation(useLoc).getBlock().getType();
|
||||||
final long flags = BlockProperties.F_CLIMBABLE | BlockProperties.F_LIQUID | BlockProperties.F_IGN_PASSABLE;
|
final long flags = BlockProperties.F_CLIMBABLE | BlockProperties.F_LIQUID | BlockProperties.F_IGN_PASSABLE;
|
||||||
if (!BlockProperties.isAir(mat) && (BlockProperties.getBlockFlags(mat) & flags) == 0 && !mcAccess.hasGravity(mat)){
|
if (!BlockProperties.isAir(mat) && (BlockProperties.getBlockFlags(mat) & flags) == 0 && !mcAccess.hasGravity(mat)){
|
||||||
// Still fails on piston traps etc.
|
// Still fails on piston traps etc.
|
||||||
if (!BlockProperties.isPassable(player.getLocation(), projectile.getLocation()) && !BlockProperties.isOnGroundOrResetCond(player, player.getLocation(), MovingConfig.getConfig(player).yOnGround)){
|
if (!BlockProperties.isPassable(player.getLocation(), projectile.getLocation()) && !BlockProperties.isOnGroundOrResetCond(player, player.getLocation(), MovingConfig.getConfig(player).yOnGround)){
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cancel) {
|
if (cancel) {
|
||||||
counters.addPrimaryThread(idEnderPearl, 1);
|
counters.addPrimaryThread(idEnderPearl, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancelled ?
|
// Cancelled ?
|
||||||
if (cancel){
|
if (cancel){
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
useLoc.setWorld(null);
|
useLoc.setWorld(null);
|
||||||
|
|
|
@ -33,19 +33,20 @@ public class Angle extends Check {
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
public boolean check(final Player player, final boolean worldChanged, final FightData data, final FightConfig cc) {
|
public boolean check(final Player player, final boolean worldChanged, final FightData data, final FightConfig cc) {
|
||||||
|
|
||||||
if (worldChanged){
|
if (worldChanged){
|
||||||
// TODO: clear some data.
|
// TODO: clear some data.
|
||||||
data.angleHits.clear();
|
data.angleHits.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean cancel = false;
|
boolean cancel = false;
|
||||||
|
|
||||||
// Remove the old locations from the map.
|
// Remove the old locations from the map.
|
||||||
|
// TODO: Use a linked list and make one iteration only (remove with Iterator).
|
||||||
for (final long time : new TreeMap<Long, Location>(data.angleHits).navigableKeySet()) {
|
for (final long time : new TreeMap<Long, Location>(data.angleHits).navigableKeySet()) {
|
||||||
if (System.currentTimeMillis() - time > 1000L) {
|
if (System.currentTimeMillis() - time > 1000L) {
|
||||||
data.angleHits.remove(time);
|
data.angleHits.remove(time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the new location to the map.
|
// Add the new location to the map.
|
||||||
|
@ -69,7 +70,7 @@ public class Angle extends Check {
|
||||||
final Location location = data.angleHits.get(time);
|
final Location location = data.angleHits.get(time);
|
||||||
// We need a previous location to calculate deltas.
|
// We need a previous location to calculate deltas.
|
||||||
if (previousLocation != null){ // && location.getWorld().getName().equals(previousLocation.getWorld().getName())) {
|
if (previousLocation != null){ // && location.getWorld().getName().equals(previousLocation.getWorld().getName())) {
|
||||||
// (Risks exceptions on reloading).
|
// (Risks exceptions on reloading).
|
||||||
// Calculate the distance between the two locations.
|
// Calculate the distance between the two locations.
|
||||||
deltaMove += previousLocation.distanceSquared(location);
|
deltaMove += previousLocation.distanceSquared(location);
|
||||||
// Calculate the time elapsed between the two hits.
|
// Calculate the time elapsed between the two hits.
|
||||||
|
@ -114,7 +115,7 @@ public class Angle extends Check {
|
||||||
if (violation > cc.angleThreshold) {
|
if (violation > cc.angleThreshold) {
|
||||||
// Has the server lagged?
|
// Has the server lagged?
|
||||||
if (TickTask.getLag(1000, true) < 1.5f){
|
if (TickTask.getLag(1000, true) < 1.5f){
|
||||||
// TODO: 1.5 is a fantasy value.
|
// TODO: 1.5 is a fantasy value.
|
||||||
// If it hasn't, increment the violation level.
|
// If it hasn't, increment the violation level.
|
||||||
data.angleVL += violation;
|
data.angleVL += violation;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user