Author SHA1 Message Date
xaw3ep 009c8d00c6 ffffffffff
Done, but not work well with recent versions; packet inversion?
2021-07-26 20:26:23 +07:00
xaw3ep aee5ed158e Parts
Put it here, syncing with local
2021-07-26 09:57:25 +07:00
483 changed files with 25506 additions and 40998 deletions

No files matched your search

+5 -9
View File
@@ -6,17 +6,13 @@ labels: ''
assignees: ''
---
#### *Complete* output of the `ncp version` command
### Output of the `ncp inspect [playername]` command for in-game issues
### Full output of /ncp version
#### Short description of the issue and how to reproduce
### Describe the issue
#### Have you made any (noteworthy) changes to the default configuration of NCP?
### How to reproduce the issue
#### Do you run any other special plugins that affect game mechanics next to NC+ (skills, machines, adding/changing blocks, other anti-cheating)?
#### Do you use **client-side** mods that could interfere with vanilla game mechanics **_(such as Optifine's FastMath)_**?
#### Provide additional information: for bypasses, vulnerabilities and reproducible issues, we request a [debug log. ](https://github.com/Updated-NoCheatPlus/Docs/blob/master/Development/Debugging.md#on-the-fly-debug-output-for-individual-players) Use [GitHub gists](https://gist.github.com/) or [PasteBin](http://pastebin.com/) or similar for errors and huge logs, or attach a (zip-) file here.
### Extra links/Videos (Including debug logs)
### Any possible config options changed or plugins that may cause interference?
@@ -40,10 +40,10 @@ public abstract class AbstractLogNodeDispatcher implements LogNodeDispatcher { /
protected int maxQueueSize = 5000;
/**
* Task id, null means the asynchronous task is not running. Synchronize over
* Task id, -1 means the asynchronous task is not running. Synchronize over
* queueAsynchronous. Must be maintained.
*/
protected Object taskAsynchronousID = null;
protected int taskAsynchronousID = -1;
/**
* Optional implementation for an asynchronous task, using the
* taskAsynchronousID, synchronized over queueAsynchronous.
@@ -57,7 +57,7 @@ public abstract class AbstractLogNodeDispatcher implements LogNodeDispatcher { /
while (i < 3) {
if (runLogsAsynchronous()) {
i = 0;
if (!isTaskScheduled(taskAsynchronousID)) {
if (taskAsynchronousID == -1) {
// Shutdown, hard return;
return;
}
@@ -69,7 +69,7 @@ public abstract class AbstractLogNodeDispatcher implements LogNodeDispatcher { /
} catch (InterruptedException e) {
synchronized (queueAsynchronous) {
// Ensure re-scheduling can happen.
taskAsynchronousID = null;
taskAsynchronousID = -1;
}
// TODO: throw?
return;
@@ -79,7 +79,7 @@ public abstract class AbstractLogNodeDispatcher implements LogNodeDispatcher { /
if (queueAsynchronous.isEmpty()) {
if (i >= 3) {
// Ensure re-scheduling can happen.
taskAsynchronousID = null;
taskAsynchronousID = -1;
}
} else {
i = 0;
@@ -134,10 +134,10 @@ public abstract class AbstractLogNodeDispatcher implements LogNodeDispatcher { /
// Cancel task.
synchronized (queueAsynchronous) {
if (isTaskScheduled(taskAsynchronousID)) {
if (taskAsynchronousID != -1) {
// TODO: Allow queues to set to "no more input" ?
cancelTask(taskAsynchronousID);
taskAsynchronousID = null;
taskAsynchronousID = -1;
} else {
// No need to wait.
ms = 0L;
@@ -184,7 +184,7 @@ public abstract class AbstractLogNodeDispatcher implements LogNodeDispatcher { /
if (queueAsynchronous.add(record) > maxQueueSize) {
reduceQueue(queueAsynchronous);
}
if (!isTaskScheduled(taskAsynchronousID)) { // Works, due to add being synchronized (not sure it's really better than full sync).
if (taskAsynchronousID == -1) { // Works, due to add being synchronized (not sure it's really better than full sync).
scheduleAsynchronous();
}
break;
@@ -242,8 +242,6 @@ public abstract class AbstractLogNodeDispatcher implements LogNodeDispatcher { /
protected abstract void scheduleAsynchronous();
protected abstract void cancelTask(Object taskInfo);
protected abstract boolean isTaskScheduled(Object taskInfo);
protected abstract void cancelTask(int taskId);
}
@@ -43,15 +43,5 @@ public class Misc {
}
list.add(0, item);
}
/**
* Flooring method copied from the BukkitAPI (locToBlock)
* @param num
* @return
*/
public static int floor(double num) {
final int floor = (int) num;
return floor == num ? floor : floor - (int) (Double.doubleToRawLongBits(num) >>> 63);
}
}
@@ -32,19 +32,12 @@ public class StringUtil {
/** Decimal format for "#.###" */
public static final DecimalFormat fdec3 = new DecimalFormat();
/** Decimal format for "#.######" */
/** Decimal format for "#.#" */
public static final DecimalFormat fdec1 = new DecimalFormat();
public static final DecimalFormat fdec6 = new DecimalFormat();
static {
DecimalFormatSymbols sym = fdec6.getDecimalFormatSymbols();
// 6 digits
sym.setDecimalSeparator('.');
fdec6.setDecimalFormatSymbols(sym);
fdec6.setMaximumFractionDigits(6);
fdec6.setMinimumIntegerDigits(1);
// 3 digits.
sym = fdec6.getDecimalFormatSymbols();
DecimalFormatSymbols sym = fdec3.getDecimalFormatSymbols();
sym.setDecimalSeparator('.');
fdec3.setDecimalFormatSymbols(sym);
fdec3.setMaximumFractionDigits(3);
@@ -408,7 +401,7 @@ public class StringUtil {
}
/**
* Format to maximally 6 digits after the comma, always show the sign,
* Format to maximally 3 digits after the comma, always show the sign,
* unless equal.
*
* @param current
@@ -416,7 +409,7 @@ public class StringUtil {
* @return
*/
public static String formatDiff(final double current, final double previous) {
return current == previous ? "0" : ((current > previous ? "+" : "-") + fdec6.format(Math.abs(current - previous)));
return current == previous ? "0" : ((current > previous ? "+" : "-") + fdec3.format(Math.abs(current - previous)));
}
public static boolean startsWithAnyOf(final String input, final String... startsWith) {
@@ -15,7 +15,7 @@
package fr.neatmonster.nocheatplus.utilities;
/**
* Simple parameter/thing for recurring validation.
* Simple parameter/thing validation.
*
* @author asofold
*
@@ -36,26 +36,5 @@ public class Validate {
}
}
}
/**
* Validates that the given double array's length: is a multiple of 6, does contain at least 1 bounding box and is not null.
*
* <p>Currently, this is rather meant to validate double arrays containing multiple bounding boxes, each defined by six consecutive elements
* [minX, minY, minZ, maxX, maxY, maxZ].<br>
*
* @param array The double array to validate.
*
* @throws IllegalArgumentException If the array length is not a multiple of 6, null or empty.
*/
public static void validateAABB(final double[] array) {
if (array == null) {
throw new NullPointerException("The array is null.");
}
if (array.length == 0) {
throw new IllegalArgumentException("The array is empty.");
}
if (array.length % 6 != 0) {
throw new IllegalArgumentException("Array length is not a multiple of 6. Actual length: " + array.length);
}
}
}
@@ -16,9 +16,9 @@ package fr.neatmonster.nocheatplus.utilities.ds.bktree;
import java.util.Collection;
import fr.neatmonster.nocheatplus.utilities.ds.bktree.BKModTree.LookupEntry;
import fr.neatmonster.nocheatplus.utilities.ds.bktree.SimpleTimedBKLevenshtein.STBKLResult;
import fr.neatmonster.nocheatplus.utilities.ds.bktree.TimedBKLevenshtein.SimpleTimedLevenNode;
import fr.neatmonster.nocheatplus.utilities.ds.bktree.BKModTree.LookupEntry;
public class SimpleTimedBKLevenshtein extends TimedBKLevenshtein<SimpleTimedLevenNode, STBKLResult> {
@@ -17,153 +17,99 @@ package fr.neatmonster.nocheatplus.utilities.ds.count;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
/**
* This class is meant to accumulate actions similar to ActionFrequency.
* In contrast to ActionFrequency, this class will accumulate values grouped by number of events instead of real-time intervals.
* @author asofold
* This class is meant to accumulate actions similar to ActionFrequency. In contrast to ActionFrequency, this class will accumulate values grouped by number of events instead of real-time intervals.
* @author mc_dev
*
*/
public class ActionAccumulator {
/** Counter of added events for each bucket. */
private final int[] valueCounter;
/** Value accumulation (sum). */
private final float[] buckets;
/** How many events can a bucket hold. */
private final int bucketCapacity;
/**
* Create a new ActionAccumulator instance
*
* @param nBuckets Number of buckets to hold values with
* @param bucketCapacity How many events can a bucket hold
*/
public ActionAccumulator(final int nBuckets, final int bucketCapacity) {
this.valueCounter = new int[nBuckets];
this.buckets = new float[nBuckets];
this.bucketCapacity = bucketCapacity;
}
/**
* Add value to accumulation (starting to the first bucket, shifting into the other ones if present)
* See shift()
*/
public void add(float value) {
if (valueCounter[0] >= bucketCapacity) {
// First bucket is full, shift data into the next one .
shift();
}
// Each time a value is added, the event counter for this bucket increases.
valueCounter[0]++ ;
// Accumulate the value
buckets[0] += value;
}
/**
* On reaching the maximum capacity of the first bucket,
* shift data into the next one and empty the first (which will be ready to accumulate values again).
*/
private void shift() {
// Start from the last bucket and decrease
for (int bucketIndex = buckets.length - 1; bucketIndex > 0; bucketIndex--) {
// Shift counted events to the next bucket
valueCounter[bucketIndex] = valueCounter[bucketIndex - 1];
// Shift accumulated values to the next bucket
buckets[bucketIndex] = buckets[bucketIndex - 1];
}
// Reset event counter of the first bucket
valueCounter[0] = 0;
// Empty the bucket (accumulated values)
buckets[0] = 0;
}
/** Event count. */
private final int[] counts;
/** Value accumulation. */
private final float[] buckets;
/** Capacity of each bucket. */
private final int bucketCapacity;
public ActionAccumulator(final int nBuckets, final int bucketCapacity){
this.counts = new int[nBuckets];
this.buckets = new float[nBuckets];
this.bucketCapacity = bucketCapacity;
}
public void add(float value){
if (counts[0] >= bucketCapacity){
shift();
}
counts[0] ++;
buckets[0] += value;
}
private void shift() {
for (int i = buckets.length - 1; i > 0 ; i--){
counts[i] = counts[i - 1];
buckets[i] = buckets[i - 1];
}
counts[0] = 0;
buckets[0] = 0;
}
/**
* Get the total accumulation value of this accumulator (values of all buckets)
*/
public float score() {
float score = 0;
for (int i = 0; i < buckets.length; i++) {
score += buckets[i];
}
return score;
}
/**
* Get the total events of the whole accumulator (of all buckets)
*/
public int count() {
int globalCounter = 0;
for (int i = 0; i < valueCounter.length; i++) {
globalCounter += valueCounter[i];
}
return globalCounter;
}
/**
* Reset all
*/
public void clear() {
for (int i = 0; i < buckets.length; i++) {
valueCounter[i] = 0;
buckets[i] = 0;
}
}
/**
* Get the events counted for this bucket
* @param bucket
* @return how many events have been added(counted) to the bucket
*/
public int bucketCount(final int bucket) {
return valueCounter[bucket];
}
/**
* Get the accumulation value of this bucket (sum of all values added to this bucket)
* @param bucket
* @return accumulation value of this bucket
*/
public float bucketScore(final int bucket) {
return buckets[bucket];
}
/**
* Get the mean of this bucket
* @param bucket
* @return the mean of this bucket
*/
public float mean(final int bucket) {
return bucketScore(bucket) / bucketCount(bucket);
}
/**
* Get the mean of the whole accumulator
*/
public float mean() {
return score() / count();
}
/**
* How many buckets does the ActionAccumulator instance have
*/
public int numberOfBuckets() {
return buckets.length;
}
/**
* How many events(count) can each bucket of the ActionAccumulator instance have
*/
public int bucketCapacity() {
return bucketCapacity;
}
/**
* Simple display of bucket contents, no class name.
*/
public String toInformalString() {
StringBuilder b = new StringBuilder(buckets.length * 10);
b.append("|");
for (int i = 0; i < buckets.length; i++){
b.append(StringUtil.fdec3.format(buckets[i]) + "/" + valueCounter[i] + "|");
}
return b.toString();
}
}
/**
* Total score.
* @return
*/
public float score(){
float score = 0;
for (int i = 0; i < buckets.length; i++){
score += buckets[i];
}
return score;
}
/**
* Total count.
* @return
*/
public int count(){
int count = 0;
for (int i = 0; i < counts.length; i++){
count += counts[i];
}
return count;
}
public void clear(){
for (int i = 0; i < buckets.length; i++){
counts[i] = 0;
buckets[i] = 0;
}
}
public int bucketCount(final int bucket){
return counts[bucket];
}
public float bucketScore(final int bucket){
return buckets[bucket];
}
public int numberOfBuckets(){
return buckets.length;
}
public int bucketCapacity(){
return bucketCapacity;
}
/**
* Simple display of bucket contents, no class name.
* @return
*/
public String toInformalString(){
StringBuilder b = new StringBuilder(buckets.length * 10);
b.append("|");
for (int i = 0; i < buckets.length; i++){
b.append(StringUtil.fdec3.format(buckets[i]) + "/" + counts[i] + "|");
}
return b.toString();
}
}
@@ -139,6 +139,24 @@ public class ActionFrequency {
time = lastUpdate = now;
}
/**
* @deprecated Use instead: score(float).
* @param factor
* @return
*/
public final float getScore(final float factor) {
return score(factor);
}
/**
* @deprecated Use instead: score(float).
* @param factor
* @return
*/
public final float getScore(final int bucket) {
return bucketScore(bucket);
}
/**
* Get a weighted sum score, weight for bucket i: w(i) = factor^i.
* @param factor
@@ -1,196 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.utilities.ds.map;
import fr.neatmonster.nocheatplus.utilities.Misc;
/**
* Integer block coordinate with support for in-place mutation.
*/
public class BlockCoord implements Cloneable {
/*
* NOTE: This class is now mutable to allow in-place addition/subtraction
* operations that do not create new instances. Because instances are
* mutable they are NOT safe to use as keys in hash-based collections if
* their coordinates may change while stored; use {@link #copy()} to get an
* immutable snapshot when needed.
*/
private int x;
private int y;
private int z;
/**
* Constructs a BlockCoord with integer coordinates.
*
* @param x The x-coordinate.
* @param y The y-coordinate.
* @param z The z-coordinate.
*/
public BlockCoord(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Constructs a BlockCoord from double coordinates by converting them
* to block integer coordinates using the same method as Bukkit's Location#locToBlock().
*
* @param x The x-coordinate.
* @param y The y-coordinate.
* @param z The z-coordinate.
*/
public BlockCoord(double x, double y, double z) {
this.x = Misc.floor(x);
this.y = Misc.floor(y);
this.z = Misc.floor(z);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
@Override
public int hashCode() {
return CoordHash.hashCode3DPrimes(x, y, z);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
BlockCoord bc = (BlockCoord) obj;
return bc.getX() == x && bc.getY() == y && bc.getZ() == z;
}
/**
* Add the given BlockCoord to this one.
*
* @param other the other BlockCoord to add to this one
* @return this (after modification)
*/
public BlockCoord add(BlockCoord other) {
return add(other.x, other.y, other.z);
}
/**
* Add the given integers to this BlockCoord.
*
* @param dx delta x
* @param dy delta y
* @param dz delta z
* @return this (after modification)
*/
public BlockCoord add(int dx, int dy, int dz) {
this.x += dx;
this.y += dy;
this.z += dz;
return this;
}
/**
* Subtract the given BlockCoord from this one.
*
* @param other the other BlockCoord to subtract
* @return this (after modification)
*/
public BlockCoord subtract(BlockCoord other) {
return subtract(other.x, other.y, other.z);
}
/**
* Subtract the given integers from this BlockCoord.
*
* @param dx delta x
* @param dy delta y
* @param dz delta z
* @return this (after modification)
*/
public BlockCoord subtract(int dx, int dy, int dz) {
this.x -= dx;
this.y -= dy;
this.z -= dz;
return this;
}
/**
* Returns the squared Euclidean distance between this block coordinate
* and another BlockCoord (integer arithmetic). Returns a double to match
* common expectations and avoid overflow for large distances.
*
* @param other the other block coordinate
* @return squared distance as a double
*/
public double distanceSquared(BlockCoord other) {
long dx = this.x - other.x;
long dy = this.y - other.y;
long dz = this.z - other.z;
return dx * dx + dy * dy + dz * dz;
}
/**
* Returns the squared Euclidean distance between this block coordinate
* and the specified integer coordinates.
*
* @param x x coordinate to compare to
* @param y y coordinate to compare to
* @param z z coordinate to compare to
* @return squared distance as a double
*/
public double distanceSquared(int x, int y, int z) {
long dx = this.x - x;
long dy = this.y - y;
long dz = this.z - z;
return dx * dx + dy * dy + dz * dz;
}
/**
* Create a copy of this BlockCoord. Returns a new independent instance
* with the same coordinates (useful when you need an immutable snapshot
* while mutating the original).
*
* @return a new BlockCoord with identical coordinates
*/
public BlockCoord copy() {
return new BlockCoord(x, y, z);
}
/**
* Clone this BlockCoord.
* <p>
* This implementation attempts to use Object#clone() (via
* super.clone()). If, for some reason,
* cloning via super is not supported (CloneNotSupportedException), we
* fall back to creating a manual copy via {@link #copy()}.
*
* @return a new BlockCoord with identical coordinates
*/
@Override
public BlockCoord clone() {
try {
return (BlockCoord) super.clone();
} catch (CloneNotSupportedException e) {
return copy();
}
}
}
@@ -14,9 +14,9 @@
*/
package fr.neatmonster.nocheatplus.utilities.ds.prefixtree;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.CharPrefixTree.CharLookupEntry;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.CharPrefixTree.SimpleCharNode;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree.SimpleCharLookupEntry;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.CharPrefixTree.CharLookupEntry;
/**
* Adding some convenience methods.
@@ -14,9 +14,9 @@
*/
package fr.neatmonster.nocheatplus.utilities.ds.prefixtree;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.PrefixTree.LookupEntry;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.PrefixTree.SimpleNode;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimplePrefixTree.SimpleLookupEntry;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.PrefixTree.LookupEntry;
/**
* Simple prefix tree, for one given key type.
@@ -14,7 +14,7 @@
*/
package fr.neatmonster.nocheatplus.test;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import org.junit.Test;
@@ -14,7 +14,7 @@
*/
package fr.neatmonster.nocheatplus.test;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import org.junit.Test;
@@ -14,7 +14,7 @@
*/
package fr.neatmonster.nocheatplus.test;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import org.junit.Test;
@@ -21,8 +21,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SplittableRandom;
import org.junit.Test;
@@ -30,8 +30,8 @@ import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
import fr.neatmonster.nocheatplus.utilities.ds.map.CoordHashMap;
import fr.neatmonster.nocheatplus.utilities.ds.map.CoordMap;
import fr.neatmonster.nocheatplus.utilities.ds.map.CoordMap.Entry;
import fr.neatmonster.nocheatplus.utilities.ds.map.LinkedCoordHashMap;
import fr.neatmonster.nocheatplus.utilities.ds.map.LinkedCoordHashMap.MoveOrder;
import fr.neatmonster.nocheatplus.utilities.ds.map.LinkedCoordHashMap;
public class TestCoordMap {
@@ -74,7 +74,7 @@ public class TestCoordMap {
private final boolean extraTesting = BuildParameters.testLevel > 0;
private final int suggestedSamples = extraTesting ? 40000 : 1250;
private static int[][] getRandomCoords(int n, int max, SplittableRandom random) {
public int[][] getRandomCoords(int n, int max, Random random) {
final int [][] coords = new int[n][3];
for (int i = 0; i < n; i++){
for (int j = 0; j < 3 ; j++){
@@ -84,7 +84,7 @@ public class TestCoordMap {
return coords;
}
private static int[][] getUniqueRandomCoords(int n, int max, SplittableRandom random) {
public int[][] getUniqueRandomCoords(int n, int max, Random random) {
Set<Pos> present = new HashSet<Pos>();
int failures = 0;
final int [][] coords = new int[n][3];
@@ -311,7 +311,7 @@ public class TestCoordMap {
@Test
public void testIntegrity() {
final SplittableRandom random = new SplittableRandom();
final Random random = new Random(System.nanoTime() - (System.currentTimeMillis() % 2 == 1 ? 37 : 137));
final int n = suggestedSamples; // Number of coordinates.
final int max = 800; // Coordinate maximum.
@@ -333,7 +333,7 @@ public class TestCoordMap {
@Test
public void testLinkedCoordHashMap() {
final SplittableRandom random = new SplittableRandom();
final Random random = new Random(System.nanoTime() - (System.currentTimeMillis() % 2 == 1 ? 37 : 137));
final int n = suggestedSamples; // Number of coordinates.
final int max = 800; // Coordinate maximum.
+1 -2
View File
@@ -19,8 +19,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<!-- Do not increase. 1.12 was the last version having its own native module -->
<version>1.21.11-R0.1-SNAPSHOT</version>
<version>1.17.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -0,0 +1,169 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.checks.inventory;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.inventory.ItemStack;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.actions.ParameterName;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.components.config.value.OverrideType;
import fr.neatmonster.nocheatplus.components.registry.feature.INotifyReload;
import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask;
/**
* Quick replacement for InstantEat, partly reusing InstantEat data.<br>
* This check is added by fr.neatmonster.nocheatplus.compat.DefaultComponentFactory.
* @author mc_dev
*
*/
public class FastConsume extends Check implements Listener, INotifyReload {
public static void testAvailability(){
if (!PlayerItemConsumeEvent.class.getSimpleName().equals("PlayerItemConsumeEvent")){
throw new RuntimeException("This exception should not even get thrown.");
}
}
private final Counters counters = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(Counters.class);
private final int idCancelDead = counters.registerKey("cancel.dead");
public FastConsume() {
super(CheckType.INVENTORY_FASTCONSUME);
// Overrides the instant-eat check.
disableInstantEat();
}
private void disableInstantEat() {
// TODO: Do this kind of thing via registries later on.
//ConfigManager.setForAllConfigs(ConfPaths.INVENTORY_INSTANTEAT_CHECK, false);
NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager().overrideCheckActivation(
CheckType.INVENTORY_INSTANTEAT, AlmostBoolean.NO,
OverrideType.PERMANENT, true);
StaticLog.logInfo("Inventory checks: FastConsume is available, disabled InstantEat.");
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onItemConsume(final PlayerItemConsumeEvent event){
final Player player = event.getPlayer();
if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) {
// Eat after death.
event.setCancelled(true);
counters.addPrimaryThread(idCancelDead, 1);
return;
}
final IPlayerData pData = DataManager.getPlayerData(player);
if (!pData.isCheckActive(type, player)) {
return;
}
final InventoryData data = pData.getGenericInstance(InventoryData.class);
final long time = System.currentTimeMillis();
if (check(player, event.getItem(), time, data, pData)){
event.setCancelled(true);
DataManager.getPlayerData(player).requestUpdateInventory();
}
}
private boolean check(final Player player, final ItemStack stack,
final long time, final InventoryData data, final IPlayerData pData){
// Uses the instant-eat data for convenience.
// Consistency checks...
if (stack == null){ // || stack.getType() != data.instantEatFood){
// TODO: Strict version should prevent other material (?).
return false;
}
final long ref = data.instantEatInteract == 0 ? 0 : Math.max(data.instantEatInteract, data.lastClickTime);
if (time < ref){
// Time ran backwards.
data.instantEatInteract = data.lastClickTime = time;
return false;
}
// Check exceptions.
final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
final Material mat = stack == null ? null : stack.getType();
if (mat != null){
if (cc.fastConsumeWhitelist){
if (!cc.fastConsumeItems.contains(mat)){
return false;
}
}
else if (cc.fastConsumeItems.contains(mat)){
return false;
}
}
// Actually check.
final long timeSpent = ref == 0 ? 0 : (time - ref); // Not interact = instant.
final long expectedDuration = cc.fastConsumeDuration;
boolean cancel = false;
if (timeSpent < expectedDuration){
// TODO: Might have to do a specialized check for lag spikes here instead.
final float lag = TickTask.getLag(expectedDuration, true);
if (timeSpent * lag < expectedDuration){
final double difference = (expectedDuration - timeSpent * lag) / 100.0;
data.instantEatVL += difference;
final ViolationData vd = new ViolationData(this, player, data.instantEatVL, difference, cc.fastConsumeActions);
vd.setParameter(ParameterName.FOOD, "" + mat);
if (data.instantEatFood != mat){
vd.setParameter(ParameterName.TAGS, "inconsistent(" + data.instantEatFood + ")");
}
else{
vd.setParameter(ParameterName.TAGS, "");
}
if (executeActions(vd).willCancel()){
cancel = true;
}
}
}
else{
data.instantEatVL *= 0.6;
}
// Reset interaction.
if (cancel) {
// Fake interaction to prevent violation loops with false positives.
final ItemStack actualStack = InventoryUtil.getFirstConsumableItemInHand(player);
data.instantEatFood = actualStack == null ? null : actualStack.getType();
// TODO: Allows some abuse: 1. try instantly eat (cancelled) 2. consume item directly when needed.
}
else {
if (pData.isDebugActive(type)) {
debug(player, "PlayerItemConsumeEvent, reset fastconsume: " + data.instantEatFood);
}
data.instantEatFood = null;
}
data.instantEatInteract = time;
return cancel;
}
@Override
public void onReload() {
disableInstantEat();
}
}
@@ -0,0 +1,64 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.checks.inventory;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerEditBookEvent;
import org.bukkit.inventory.meta.BookMeta;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
public class Gutenberg extends Check implements Listener {
public static void testAvailability(){
if (!PlayerEditBookEvent.class.getSimpleName().equals("PlayerEditBookEvent")){
throw new RuntimeException("This exception should not even get thrown.");
}
}
public Gutenberg() {
super(CheckType.INVENTORY_GUTENBERG);
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEditBook(final PlayerEditBookEvent event) {
final Player player = event.getPlayer();
if (!isEnabled(player)) {
return;
}
final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
final InventoryData data = pData.getGenericInstance(InventoryData.class);
final BookMeta newMeta = event.getNewBookMeta();
final int pages = newMeta.getPageCount();
if (pages <= cc.gutenbergPageLimit) {
// Legitimate.
return;
}
// Violation.
final int vl = pages - cc.gutenbergPageLimit;
data.gutenbergVL += vl;
if (executeActions(player, data.gutenbergVL, vl, cc.gutenbergActions).willCancel()) {
event.setCancelled(true);
}
}
}
@@ -26,7 +26,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPortalEnterEvent;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.compat.bukkit.BridgeMaterial;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
@@ -14,10 +14,6 @@
*/
package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
@@ -25,21 +21,11 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import fr.neatmonster.nocheatplus.compat.Bridge1_13;
import fr.neatmonster.nocheatplus.compat.SchedulerHelper;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
public class BlockCacheBukkit extends BlockCache {
private static final long FOLIA_FALLBACK_LOG_INTERVAL_MS = 10000L;
private static final int FOLIA_FALLBACK_CONSOLE_LOG_MIN_COUNT = 2;
private static final AtomicInteger foliaFallbackCount = new AtomicInteger();
private static final AtomicInteger foliaFallbackResolvedCount = new AtomicInteger();
private static final AtomicLong nextFoliaFallbackLog = new AtomicLong();
protected World world;
/** Temporary use. Use LocUtil.clone before passing on. Call setWorld(null) after use. */
@@ -62,99 +48,20 @@ public class BlockCacheBukkit extends BlockCache {
@Override
public Material fetchTypeId(final int x, final int y, final int z) {
// TODO: consider setting type id and data at once.
if (world == null) {
return Material.AIR;
}
if (SchedulerHelper.isOwnedByCurrentRegion(world, x, z)) {
return world.getBlockAt(x, y, z).getType();
}
final Material fallbackType = fetchTypeIdWithLocationFallback(x, y, z);
return fallbackType == null ? Material.AIR : fallbackType;
return world.getBlockAt(x, y, z).getType();
}
@SuppressWarnings("deprecation")
@Override
public int fetchData(final int x, final int y, final int z) {
// TODO: consider setting type id and data at once.
if (world == null) {
return 0;
}
if (SchedulerHelper.isOwnedByCurrentRegion(world, x, z)) {
return Bridge1_13.hasIsSwimming() ? 0 : world.getBlockAt(x, y, z).getData();
}
final Integer fallbackData = fetchDataWithLocationFallback(x, y, z);
return fallbackData == null ? 0 : fallbackData.intValue();
return Bridge1_13.hasIsSwimming() ? 0 : world.getBlockAt(x, y, z).getData();
}
private Material fetchTypeIdWithLocationFallback(final int x, final int y, final int z) {
// Folia compatibility: if the chunk-level ownership check cannot prove safety, retry the exact location.
// If that also fails, keep AIR as the safe final fallback instead of touching another region's block state.
boolean resolved = false;
try {
if (SchedulerHelper.isOwnedByCurrentRegion(new Location(world, x, y, z))) {
resolved = true;
return world.getBlockAt(x, y, z).getType();
}
}
catch (Throwable t) {
// Keep the final AIR fallback for servers that throw while checking ownership or block state.
}
finally {
logFoliaBlockFallback("type", resolved);
}
return null;
}
@SuppressWarnings("deprecation")
private Integer fetchDataWithLocationFallback(final int x, final int y, final int z) {
// Folia compatibility: retry exact-location ownership before returning legacy data 0 as the final fallback.
boolean resolved = false;
try {
if (SchedulerHelper.isOwnedByCurrentRegion(new Location(world, x, y, z))) {
resolved = true;
return Integer.valueOf(Bridge1_13.hasIsSwimming() ? 0 : world.getBlockAt(x, y, z).getData());
}
}
catch (Throwable t) {
// Keep the final data 0 fallback for servers that throw while checking ownership or block state.
}
finally {
logFoliaBlockFallback("data", resolved);
}
return null;
}
private static void logFoliaBlockFallback(final String kind, final boolean resolved) {
if (!CheckUtils.shouldLogDebugToConsole()) {
return;
}
final int count = foliaFallbackCount.incrementAndGet();
if (resolved) {
foliaFallbackResolvedCount.incrementAndGet();
}
final long now = System.currentTimeMillis();
final long next = nextFoliaFallbackLog.get();
if (now < next || !nextFoliaFallbackLog.compareAndSet(next, now + FOLIA_FALLBACK_LOG_INTERVAL_MS)) {
return;
}
final int resolvedCount = foliaFallbackResolvedCount.getAndSet(0);
final int periodCount = foliaFallbackCount.getAndSet(0);
// Folia diagnostic: a single safe fallback during teleport/chunk handoff is expected and not useful console noise.
if (periodCount < FOLIA_FALLBACK_CONSOLE_LOG_MIN_COUNT) {
return;
}
Bukkit.getLogger().info("[NCP][Folia][BlockCache] safe " + kind + " block fallback used "
+ periodCount + " times in the last 10s, resolved=" + resolvedCount
+ ", finalSafeFallback=" + (periodCount - resolvedCount) + ".");
}
@Override
public double[] fetchBounds(final int x, final int y, final int z){
Material mat = getType(x, y, z);
long flags = BlockFlags.getBlockFlags(mat);
if (flags == BlockFlags.F_IGN_PASSABLE_CHECK) {
return null;
}
// minX, minY, minZ, maxX, maxY, maxZ
// TODO: Want to maintain a list with manual entries or at least half / full blocks ?
// Always return full bounds, needs extra adaption to BlockProperties (!).
return new double[]{0D, 0D, 0D, 1D, 1D, 1D};
@@ -162,24 +69,21 @@ public class BlockCacheBukkit extends BlockCache {
@Override
public boolean standsOnEntity(final Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
if (!SchedulerHelper.isOwnedByCurrentRegion(entity)) {
return false;
}
try{
// TODO: Probably check other ids too before doing this ?
for (final Entity other : entity.getNearbyEntities(2.0, 2.0, 2.0)){
if (!SchedulerHelper.isOwnedByCurrentRegion(other)) {
continue;
}
final EntityType type = other.getType();
if (!MaterialUtil.isBoat(type) && type != EntityType.SHULKER){ // && !(other instanceof Minecart))
continue;
if (type != EntityType.BOAT && type != EntityType.SHULKER){ // && !(other instanceof Minecart))
continue;
}
final double locY = entity.getLocation(useLoc).getY();
useLoc.setWorld(null);
// TODO: A "better" estimate is possible, though some more tolerance would be good.
return Math.abs(locY - minY) < 0.7;
}
if (Math.abs(locY - minY) < 0.7){
// TODO: A "better" estimate is possible, though some more tolerance would be good.
return true;
}
else return false;
}
}
catch (Throwable t){
// Ignore exceptions (Context: DisguiseCraft).
@@ -196,25 +100,4 @@ public class BlockCacheBukkit extends BlockCache {
world = null;
}
@Override
public double[] fetchVisualBounds(int x, int y, int z) {
Material mat = getType(x, y, z);
long flags = BlockFlags.getBlockFlags(mat);
if (flags == BlockFlags.F_IGN_PASSABLE_CHECK) {
return null;
}
// TODO: Want to maintain a list with manual entries or at least half / full blocks ?
// Always return full bounds, needs extra adaption to BlockProperties (!).
return new double[]{0D, 0D, 0D, 1D, 1D, 1D};
}
@Override
public boolean isCollisionSameVisual(int x, int y, int z) {
return true;
}
@Override
public long fetchExtendedData(int x, int y, int z) {
return 0;
}
}
}
@@ -16,20 +16,10 @@ package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.Map;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import fr.neatmonster.nocheatplus.compat.SchedulerHelper;
import fr.neatmonster.nocheatplus.compat.bukkit.model.BukkitShapeModel;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
/**
@@ -39,21 +29,22 @@ import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
*
*/
public class BlockCacheBukkitModern extends BlockCacheBukkit {
private Map<Material, BukkitShapeModel> shapeModels;
public BlockCacheBukkitModern(Map<Material, BukkitShapeModel> shapeModels) {
super(null);
this.shapeModels = shapeModels;
}
public BlockCacheBukkitModern(World world) {
super(world);
}
@Override
public int fetchData(int x, int y, int z) {
Material mat = getType(x, y, z);
final BukkitShapeModel shapeModel = shapeModels.get(mat);
if (shapeModel != null) {
final int data = shapeModel.getFakeData(this, world, x, y, z);
@@ -64,93 +55,29 @@ public class BlockCacheBukkitModern extends BlockCacheBukkit {
return super.fetchData(x, y, z);
}
@Override
public long fetchExtendedData(final int x, final int y, final int z) {
if (world == null) {
return 0L;
}
// Folia support: only query live Bukkit block data from the owning region thread.
if (SchedulerHelper.isOwnedByCurrentRegion(world, x, z)) {
return fetchWaterloggedFlags(x, y, z);
}
try {
if (SchedulerHelper.isOwnedByCurrentRegion(new Location(world, x, y, z))) {
return fetchWaterloggedFlags(x, y, z);
}
} catch (Throwable ignored) {
// Keep the cache fallback conservative if the scheduler API is unavailable.
}
return 0L;
}
private long fetchWaterloggedFlags(final int x, final int y, final int z) {
final IPlayerData pData = getPlayerData();
if (pData != null && pData.getClientVersion().isLowerThan(ClientVersion.V_1_13)) {
return 0L;
}
final BlockData data = world.getBlockAt(x, y, z).getBlockData();
if (data instanceof Waterlogged && ((Waterlogged) data).isWaterlogged()) {
return BlockFlags.F_WATER | BlockFlags.F_LIQUID | BlockFlags.F_WATERLOGGED;
}
return 0L;
}
@Override
public double[] fetchBounds(int x, int y, int z) {
// minX, minY, minZ, maxX, maxY, maxZ
// TODO: Fetch what's possible to fetch/guess (...).
// TODO: Consider to store the last used block/stuff within BlockCacheBukkit already.
//final Block block = world.getBlockAt(x, y, z);
//final BlockState state = block.getState();
//final MaterialData materialData = state.getData();
//final BlockData blockData = state.getBlockData();
Material mat = getType(x, y, z);
final BukkitShapeModel shapeModel = shapeModels.get(mat);
if (shapeModel == null) {
return super.fetchBounds(x, y, z);
}
return shapeModel.getShape(this, world, x, y, z);
else {
return shapeModel.getShape(this, world, x, y, z);
}
}
@Override
public double[] fetchVisualBounds(int x, int y, int z) {
Material mat = getType(x, y, z);
final BukkitShapeModel shapeModel = shapeModels.get(mat);
if (shapeModel == null) {
return super.fetchVisualBounds(x, y, z);
}
return shapeModel.getVisualShape(this, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(int x, int y, int z) {
Material mat = getType(x, y, z);
final BukkitShapeModel shapeModel = shapeModels.get(mat);
if (shapeModel == null) {
return super.isCollisionSameVisual(x, y, z);
}
return shapeModel.isCollisionSameVisual(this, world, x, y, z);
}
@Override
public boolean standsOnEntity(final Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ) {
if (!SchedulerHelper.isOwnedByCurrentRegion(entity)) {
return false;
}
try {
// TODO: Probably check vehicle ids too before doing this ?
for (final Entity vehicle : entity.getNearbyEntities(0.1, 2.0, 0.1)) {
if (!SchedulerHelper.isOwnedByCurrentRegion(vehicle)) {
continue;
}
final EntityType type = vehicle.getType();
if (!MaterialUtil.isBoat(type) && type != EntityType.SHULKER) { // && !(vehicle instanceof Minecart))
continue;
}
final double vehicleY = vehicle.getLocation(useLoc).getY() + vehicle.getHeight();
final double entityY = entity.getLocation(useLoc).getY();
useLoc.setWorld(null);
// TODO: A "better" estimate is possible, though some more tolerance would be good.
return vehicleY < entityY + 0.1 && Math.abs(vehicleY - entityY) < 0.7;
}
} catch (Throwable t) {
// Ignore exceptions (Context: DisguiseCraft).
}
return false;
}
// TODO: Might refine standsOnEntity as well.
}
@@ -16,27 +16,15 @@ package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.UUID;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.attribute.AttributeModifier.Operation;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData;
import fr.neatmonster.nocheatplus.compat.AttribUtil;
import fr.neatmonster.nocheatplus.compat.Bridge1_13;
import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.compat.registry.BukkitAPIAccessFactory;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
import fr.neatmonster.nocheatplus.utilities.math.MathUtil;
import fr.neatmonster.nocheatplus.utilities.moving.Magic;
public class BukkitAttributeAccess implements IAttributeAccess {
@@ -67,7 +55,6 @@ public class BukkitAttributeAccess implements IAttributeAccess {
* @param id
* @return
*/
@SuppressWarnings({"deprecation", "removal"})
private AttributeModifier getModifier(final AttributeInstance attrInst, final UUID id) {
for (final AttributeModifier mod : attrInst.getModifiers()) {
if (id.equals(mod.getUniqueId())) {
@@ -80,208 +67,20 @@ public class BukkitAttributeAccess implements IAttributeAccess {
private double getMultiplier(final AttributeModifier mod) {
return AttribUtil.getMultiplier(operationToInt(mod.getOperation()), mod.getAmount());
}
@Override
public float getMovementSpeed(final Player player) {
// / by 2 to get the base value 0.1f
return (player.getWalkSpeed() / 2f) * (float) getSpeedMultiplier(player);
}
@Override
public double getSpeedMultiplier(final Player player) {
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getSpeedAttributeInstance(player);
public double getSpeedAttributeMultiplier(final Player player) {
final AttributeInstance attrInst = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
final double val = attrInst.getValue() / attrInst.getBaseValue();
final AttributeModifier mod = getModifier(attrInst, AttribUtil.ID_SPRINT_BOOST);
return mod == null ? val : (val / getMultiplier(mod));
}
@Override
public double getSprintMultiplier(final Player player) {
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getSpeedAttributeInstance(player);
public double getSprintAttributeMultiplier(final Player player) {
final AttributeInstance attrInst = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
final AttributeModifier mod = getModifier(attrInst, AttribUtil.ID_SPRINT_BOOST);
return mod == null ? 1.0 : getMultiplier(mod);
}
@Override
public double getGravity(Player player) {
double gravity;
final PlayerMoveData thisMove = DataManager.getPlayerData(player).getGenericInstance(MovingData.class).playerMoves.getCurrentMove();
if (!BridgeMisc.hasGravity(player)) {
return 0.0;
}
if (ServerVersion.isLowerThan("1.20.5")) {
// Doesn't exist. Calculate manually.
gravity = thisMove.yDistance <= 0.0 && !Double.isInfinite(Bridge1_13.getSlowfallingAmplifier(player)) ? Magic.SLOW_FALL_GRAVITY : Magic.DEFAULT_GRAVITY;
}
else {
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getGravityAttributeInstance(player);
// Fail-safe.
if (attrInst == null) {
gravity = thisMove.yDistance <= 0.0 && !Double.isInfinite(Bridge1_13.getSlowfallingAmplifier(player)) ? Magic.SLOW_FALL_GRAVITY : Magic.DEFAULT_GRAVITY;
}
else gravity = MathUtil.clamp(attrInst.getValue(), -1.0, 1.0);
if (thisMove.yDistance <= 0.0 && !Double.isInfinite(Bridge1_13.getSlowfallingAmplifier(player))) {
gravity = Math.min(gravity, Magic.SLOW_FALL_GRAVITY);
}
}
return gravity;
}
@Override
public double getSafeFallDistance(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
// Doesn't exist. Calculate manually.
return Magic.FALL_DAMAGE_DIST;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getSafeFallAttributeInstance(player);
// Fail-safe
if (attrInst == null) return Magic.FALL_DAMAGE_DIST;
return MathUtil.clamp(attrInst.getValue(), -1024.0, 1024.0);
}
@Override
public double getFallDamageMultiplier(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
// Doesn't exist. Calculate manually.
return 1.0;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getFallMultAttributeInstance(player);
// Fail-safe
if (attrInst == null) return 1.0;
return MathUtil.clamp(attrInst.getValue(), 1.0, 100.0);
}
@Override
public double getBreakingSpeedMultiplier(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
// Doesn't exist. Calculate manually.
return 1.0;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getBreakSpeedAttributeInstance(player);
// Fail-safe
if (attrInst == null) return 1.0;
return MathUtil.clamp(attrInst.getValue(), 1.0, 1024.0);
}
@Override
public double getJumpGainMultiplier(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
// Doesn't exist. Calculate manually.
return 1.0;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getJumpPowerAttributeInstance(player);
// Fail-safe
if (attrInst == null) return 1.0;
final double val = attrInst.getValue() / attrInst.getBaseValue();
return MathUtil.clamp(val, 0.0, 76.19047619047619); // MathUtil.clamp(attrInst.getValue(), 0.0, 32.0);
}
@Override
public double getPlayerSneakingFactor(Player player) {
// Not available. 1.21 and above only.
return Magic.SNEAK_MULTIPLIER + BridgeEnchant.getSwiftSneakIncrement(player);
}
@Override
public double getPlayerMaxBlockReach(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
// Doesn't exist. Calculate manually.
return 4.5;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getBlockInteractionRangeAttributeInstance(player);
// Fail-safe
if (attrInst == null) return 4.5;
return MathUtil.clamp(attrInst.getValue(), 0.0, 64.0);
}
@Override
public double getPlayerMaxAttackReach(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
// Doesn't exist. Calculate manually.
return 3.0;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getEntityInteractionRangeAttributeInstance(player);
// Fail-safe
if (attrInst == null) return 3.0;
return MathUtil.clamp(attrInst.getValue(), 0.0, 64.0);
}
@Override
public double getMaxStepUp(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
// Does not exist, calculate manually.
if (player.isInsideVehicle()) {
if (player.getVehicle() != null && MaterialUtil.isBoat(player.getVehicle().getType())) {
// Boats are unable to step.
return 0.0;
}
// All other vehicles have a step value of 1.0
return 1.0;
}
final MovingConfig cc = DataManager.getPlayerData(player).getGenericInstance(MovingConfig.class);
return cc.sfStepHeight;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getStepHeightAttributeInstance(player);
if (attrInst == null) {
// Fail-safe.
if (player.isInsideVehicle()) {
if (player.getVehicle() != null && MaterialUtil.isBoat(player.getVehicle().getType())) {
return 0.0;
}
return 1.0;
}
final MovingConfig cc = DataManager.getPlayerData(player).getGenericInstance(MovingConfig.class);
return cc.sfStepHeight;
}
return MathUtil.clamp(attrInst.getValue(), 0.0, 10.0);
}
@Override
public float getWaterMovementEfficiency(Player player) {
final IPlayerData pData = DataManager.getPlayerData(player);
if (pData.getClientVersion().isLowerThan(ClientVersion.V_1_8)) {
// Doesn't exist.
return 0f;
}
final float depthStrider = BridgeEnchant.getDepthStriderLevel(player);
if (pData.getClientVersion().isLowerThan(ClientVersion.V_1_21)) {
// Use the legacy method.
return depthStrider;
}
if (ServerVersion.isLowerThan("1.21")) {
// Simulate what ViaVersion does for newer (1.21 clients) on older (1.21-) servers.
return depthStrider / 3.0f;
}
// Unsupported. Only since 1.21.
return depthStrider;
}
@Override
public float getMovementEfficiency(Player player) {
// Not available. 1.21 and above only.
return 0.0f;
}
@Override
public double getSubmergedMiningSpeedMultiplier(Player player) {
// Not available. 1.21 and above only.
return 1.0;
}
@Override
public double getMiningEfficiency(Player player) {
// Not available. 1.21 and above only.
return 0.0;
}
@Override
public double getEntityScale(Player player) {
if (ServerVersion.isLowerThan("1.20.5")) {
return 1.0;
}
final AttributeInstance attrInst = BukkitAPIAccessFactory.getBukkitAccess().getScaleAttributeInstance(player);
// Fail-safe.
if (attrInst == null) return 1.0;
return MathUtil.clamp(attrInst.getValue(), 0.0625, 16.0);
}
}
@@ -25,6 +25,7 @@ import fr.neatmonster.nocheatplus.config.WorldConfigProvider;
import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertiesSetup {
@@ -41,10 +42,10 @@ public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertie
}
else if (guessItchyBlock(mat)) {
// Uncertain bounding-box, allow passing through.
long flags = BlockFlags.F_IGN_PASSABLE_CHECK;
long flags = BlockProperties.F_IGN_PASSABLE;
if ((BlockFlags.hasAnyFlag(flags, BlockFlags.SOLID_GROUND))) {
// Block can be ground, so allow standing on any height.
flags |= BlockFlags.F_GROUND | BlockFlags.F_GROUND_HEIGHT;
flags |= BlockProperties.F_GROUND | BlockProperties.F_GROUND_HEIGHT;
}
/*
* TODO: Might have to set all blocks to ground here, rather
@@ -32,10 +32,10 @@ import org.bukkit.entity.Slime;
import org.bukkit.potion.PotionEffectType;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.utilities.PotionUtil;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.entity.PotionUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
@@ -75,17 +75,17 @@ public class MCAccessBukkitBase implements MCAccess {
return false;
}
// Fully solid/ground blocks.
final long flags = BlockFlags.getBlockFlags(mat);
final long flags = BlockProperties.getBlockFlags(mat);
/*
* Skip fully passable blocks (partially passable blocks may be itchy,
* though slabs will be easy to handle).
*/
if (BlockFlags.hasAnyFlag(flags, BlockFlags.F_IGN_PASSABLE_CHECK)) {
if (BlockFlags.hasAnyFlag(flags, BlockProperties.F_IGN_PASSABLE)) {
// TODO: Blocks with min_height may actually be ok, if xz100 and some height are set.
if (BlockFlags.hasNoFlags(flags,
BlockFlags.F_GROUND_HEIGHT
| BlockFlags.F_GROUND
| BlockFlags.F_SOLID)) {
BlockProperties.F_GROUND_HEIGHT
| BlockProperties.F_GROUND
| BlockProperties.F_SOLID)) {
// Explicitly passable.
return false;
}
@@ -94,10 +94,11 @@ public class MCAccessBukkitBase implements MCAccess {
return true;
}
}
long testFlags1 = (BlockFlags.F_SOLID | BlockFlags.F_XZ100);
long testFlags2 = (BlockFlags.F_HEIGHT100);
if (BlockFlags.hasAllFlags(flags, testFlags1) && BlockFlags.hasAnyFlag(flags, testFlags2)) {
long testFlags1 = (BlockProperties.F_SOLID | BlockProperties.F_XZ100);
long testFlags2 = (BlockProperties.F_HEIGHT100
| BlockProperties.F_HEIGHT16_15);
if (BlockFlags.hasAllFlags(flags, testFlags1)
&& BlockFlags.hasAnyFlag(flags, testFlags2)) {
// Solid blocks with explicitly set bounds.
return false;
}
@@ -113,9 +114,9 @@ public class MCAccessBukkitBase implements MCAccess {
@Override
public String getMCVersion() {
// Bukkit API. Versions lower than MC 1.13 have their own module.
// Bukkit API.
// TODO: maybe output something else.
return "1.13-1.20"; // uh oh
return "1.4.6-1.15.2|?"; // uh oh
}
@Override
@@ -174,16 +175,12 @@ public class MCAccessBukkitBase implements MCAccess {
// TODO: For height too. [Automatize most by spawning + checking?]
// Values taken from 1.7.10.
final EntityType type = entity.getType();
Double width = BridgeEntityType.LEGACY_ENTITY_WIDTH.get(type);
if (width != null) {
return width;
}
switch(type){
// TODO: case COMPLEX_PART:
//case ENDER_SIGNAL: // this.a(0.25F, 0.25F);
//case FIREWORK: // this.a(0.25F, 0.25F);
//case FISHING_HOOK: // this.a(0.25F, 0.25F);
//case DROPPED_ITEM: // this.a(0.25F, 0.25F);
case ENDER_SIGNAL: // this.a(0.25F, 0.25F);
case FIREWORK: // this.a(0.25F, 0.25F);
case FISHING_HOOK: // this.a(0.25F, 0.25F);
case DROPPED_ITEM: // this.a(0.25F, 0.25F);
case SNOWBALL: // (projectile) this.a(0.25F, 0.25F);
return 0.25;
case CHICKEN: // this.a(0.3F, 0.7F);
@@ -193,7 +190,7 @@ public class MCAccessBukkitBase implements MCAccess {
case WITHER_SKULL: // this.a(0.3125F, 0.3125F);
return 0.3125f;
case GHAST: // this.a(4.0F, 4.0F);
//case SNOWMAN: // this.a(0.4F, 1.8F);
case SNOWMAN: // this.a(0.4F, 1.8F);
return 0.4f;
case ARROW: // this.a(0.5F, 0.5F);
case BAT: // this.a(0.5F, 0.9F);
@@ -215,24 +212,24 @@ public class MCAccessBukkitBase implements MCAccess {
case CAVE_SPIDER: // this.a(0.7F, 0.5F);
return 0.7f;
case COW: // this.a(0.9F, 1.3F);
//case MUSHROOM_COW: // this.a(0.9F, 1.3F);
case MUSHROOM_COW: // this.a(0.9F, 1.3F);
case PIG: // this.a(0.9F, 0.9F);
case SHEEP: // this.a(0.9F, 1.3F);
case WITHER: // this.a(0.9F, 4.0F);
return 0.9f;
case SQUID: // this.a(0.95F, 0.95F);
return 0.95f;
//case PRIMED_TNT: // this.a(0.98F, 0.98F);
// return 0.98f;
case PRIMED_TNT: // this.a(0.98F, 0.98F);
return 0.98f;
case FIREBALL: // (EntityFireball) this.a(1.0F, 1.0F);
return 1.0f;
case IRON_GOLEM: // this.a(1.4F, 2.9F);
case SPIDER: // this.a(1.4F, 0.9F);
return 1.4f;
// case BOAT: // this.a(1.5F, 0.6F);
// return 1.5f;
//case ENDER_CRYSTAL: // this.a(2.0F, 2.0F);
// return 2.0f;
case BOAT: // this.a(1.5F, 0.6F);
return 1.5f;
case ENDER_CRYSTAL: // this.a(2.0F, 2.0F);
return 2.0f;
case GIANT: // this.height *= 6.0F; this.a(this.width * 6.0F, this.length * 6.0F);
return 3.6f; // (Better than nothing.)
case ENDER_DRAGON: // this.a(16.0F, 8.0F);
@@ -247,9 +244,6 @@ public class MCAccessBukkitBase implements MCAccess {
default:
break;
}
if (MaterialUtil.isBoat(entity.getType())) {
return ServerVersion.isHigherThan("1.8") ? 1.3964844f : 1.4f;
}
// Check by instance for minecarts (too many).
if (entity instanceof Minecart) {
return 0.98f; // this.a(0.98F, 0.7F);
@@ -257,8 +251,8 @@ public class MCAccessBukkitBase implements MCAccess {
// Latest Bukkit API.
try {
switch (type) {
//case LEASH_HITCH: // hanging: this.a(0.5F, 0.5F);
// return 0.5f;
case LEASH_HITCH: // hanging: this.a(0.5F, 0.5F);
return 0.5f;
case HORSE: // this.a(1.4F, 1.6F);
return 1.4f;
// 1.8
@@ -315,7 +309,7 @@ public class MCAccessBukkitBase implements MCAccess {
@Override
public double getJumpAmplifier(final Player player) {
return PotionUtil.getPotionEffectAmplifier(player, BridgePotionEffect.JUMP_BOOST);
return PotionUtil.getPotionEffectAmplifier(player, PotionEffectType.JUMP);
}
@Override
@@ -21,116 +21,130 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.compat.blocks.init.BlockInit;
import fr.neatmonster.nocheatplus.compat.bukkit.model.*;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectBase;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectDamageSource;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectDamageSources;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectLivingEntity;
import fr.neatmonster.nocheatplus.config.WorldConfigProvider;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
public class MCAccessBukkitModern extends MCAccessBukkit {
protected ReflectBase reflectBase = null;
protected ReflectDamageSource reflectDamageSource = null;
protected ReflectDamageSources reflectDamageSources = null;
protected ReflectLivingEntity reflectLivingEntity = null;
protected final Map<Material, BukkitShapeModel> shapeModels = new HashMap<Material, BukkitShapeModel>();
// Blocks that can be fetched automatically from the Bukkit API
private static final BukkitShapeModel MODEL_AUTO_FETCH = new BukkitFetchableBounds();
private static final BukkitShapeModel MODEL_AUTO_FETCH_LEGACY = new BukkitFetchableBound();
// Blocks that can automatic fetch bounding box from API
private static final BukkitShapeModel MODEL_AUTO_FETCH = new BukkitFetchableBound();
// Blocks that are formed from multiple bounding boxes
// Blocks that form from multi-bounds
private static final BukkitShapeModel MODEL_BREWING_STAND = new BukkitStatic(
// Bottom rod
0.0625, 0.0, 0.0625, 0.9375, 0.125, 0.9375,
// Rod
0.4375, 0.125, 0.4375, 0.5625, 0.875, 0.5625
);
// Bottom rod
0.0625, 0.0, 0.0625, 0.9375, 0.125, 0.9375,
// Rod
0.4375, 0.125, 0.4375, 0.5625, 0.8749, 0.5625);
private static final BukkitShapeModel MODEL_CANDLE_CAKE = new BukkitStatic(
// Cake
0.0625, 0.0, 0.0625, 0.9375, 0.5, 0.9375,
// Candle
0.4375, 0.5, 0.4375, 0.5625, 0.875, 0.5625
);
// Cake
0.0625, 0.0, 0.0625, 0.9375, 0.5, 0.9375,
// Candle
0.4375, 0.5, 0.4375, 0.5625, 0.875, 0.5625);
private static final BukkitShapeModel MODEL_LECTERN = new BukkitStatic(
// Post
0.0, 0.0, 0.0, 1.0, 0.125, 1.0,
// Lectern
0.25, 0.125, 0.25, 0.75, 0.875, 0.75
);
0.0, 0.0, 0.0, 1.0, 0.125, 1.0,
0.25, 0.125, 0.25, 0.75, 0.875, 0.75);
private static final BukkitShapeModel MODEL_HOPPER = new BukkitHopper();
private static final BukkitShapeModel MODEL_CAULDRON = new BukkitCauldron();
private static final BukkitShapeModel MODEL_COMPOSTER = new BukkitComposter(0.0, 0.125, 1.0, 0.125);
private static final BukkitShapeModel MODEL_CAULDRON = new BukkitCauldron(0.1875, 0.125, 0.8125, 0.0625);
private static final BukkitShapeModel MODEL_COMPOSTER = new BukkitCauldron(0.0, 0.125, 1.0, 0.125);
private static final BukkitShapeModel MODEL_PISTON_HEAD = new BukkitPistonHead();
private static final BukkitShapeModel MODEL_BELL = new BukkitBell();
private static final BukkitShapeModel MODEL_ANVIL = new BukkitAnvil();
private static final BukkitShapeModel MODEL_GRIND_STONE = new BukkitGrindStone();
// Blocks that change shape based on interaction or redstone.
private static final BukkitShapeModel MODEL_DOOR = new BukkitDoor();
private static final BukkitShapeModel MODEL_TRAP_DOOR = new BukkitTrapDoor();
private static final BukkitShapeModel MODEL_GATE = new BukkitGate(0.375, 1.5);
private static final BukkitShapeModel MODEL_GATE = new BukkitGate(
0.375, 1.5);
private static final BukkitShapeModel MODEL_SHULKER_BOX = new BukkitShulkerBox();
private static final BukkitShapeModel MODEL_CHORUS_PLANT = new BukkitChorusPlant();
private static final BukkitShapeModel MODEL_DRIP_LEAF = new BukkitDripLeaf();
// Blocks with different heights based on whatever.
private static final BukkitShapeModel MODEL_END_PORTAL_FRAME = new BukkitEndPortalFrame();
private static final BukkitShapeModel MODEL_SEA_PICKLE = new BukkitSeaPickle();
private static final BukkitShapeModel MODEL_COCOA = new BukkitCocoa();
private static final BukkitShapeModel MODEL_TURTLE_EGG = new BukkitTurtleEgg();
private static final BukkitShapeModel MODEL_POWDER_SNOW = new BukkitPowderSnow();
// Blocks that have a different shape, based on how they have been placed.
private static final BukkitShapeModel MODEL_CAKE = new BukkitCake();
private static final BukkitShapeModel MODEL_SLAB = new BukkitSlab();
private static final BukkitShapeModel MODEL_STAIRS = new BukkitStairs();
private static final BukkitShapeModel MODEL_SNOW = new BukkitSnow();
private static final BukkitShapeModel MODEL_PISTON = new BukkitPiston();
private static final BukkitShapeModel MODEL_LEVELLED = new BukkitLevelled();
private static final BukkitShapeModel MODEL_LADDER = new BukkitLadder();
private static final BukkitShapeModel MODEL_RAIL = new BukkitRail();
private static final BukkitShapeModel MODEL_END_ROD = new BukkitDirectionalCentered(0.375, 1.0, false);
private static final BukkitShapeModel MODEL_END_ROD = new BukkitDirectionalCentered(
0.375, 1.0, false);
// Blocks that have a different shape with neighbor blocks (bukkit takes care though).
private static final BukkitShapeModel MODEL_THIN_FENCE = new BukkitFence(0.4375, 1.0, true);
private static final BukkitShapeModel MODEL_THICK_FENCE = new BukkitFence(0.375, 1.5, false);
private static final BukkitShapeModel MODEL_THICK_FENCE2 = new BukkitWall(0.25, 1.5, 0.3125); // .75 .25 0 max: .25 .75 .5
private static final BukkitShapeModel MODEL_THIN_FENCE = new BukkitFence(
0.4375, 1.0);
private static final BukkitShapeModel MODEL_THICK_FENCE = new BukkitFence(
0.375, 1.5);
private static final BukkitShapeModel MODEL_THICK_FENCE2 = new BukkitWall(
0.25, 1.5, 0.3125);
// .75 .25 0 max: .25 .75 .5
private static final BukkitShapeModel MODEL_WALL_HEAD = new BukkitWallHead();
// Static blocks (various height and inset values).
private static final BukkitShapeModel MODEL_CAMPFIRE = new BukkitStatic(0.0, 0.4375);
private static final BukkitShapeModel MODEL_BAMBOO = new BukkitBamboo();
private static final BukkitShapeModel MODEL_POINTED_DRIPSTONE = new BukkitDripStone();
private static final BukkitShapeModel MODEL_SCAFFOLDING = new BukkitScaffolding();
private static final BukkitShapeModel MODEL_WATER_PLANTS = new BukkitWaterPlant();
private static final BukkitShapeModel MODEL_LILY_PAD = new BukkitLilyPad();
private static final BukkitShapeModel MODEL_FLOWER_POT = new BukkitStatic(0.3125, 0.375);
private static final BukkitShapeModel MODEL_LILY_PAD = new BukkitStatic(
0.09375);
private static final BukkitShapeModel MODEL_FLOWER_POT = new BukkitStatic(
0.33, 0.375); // TODO: XZ really?
private static final BukkitShapeModel MODEL_LANTERN = new BukkitLantern();
private static final BukkitShapeModel MODEL_CONDUIT = new BukkitStatic(0.3125, 0.3125, 0.3125, 0.6875, 0.6875, 0.6875);
private static final BukkitShapeModel MODEL_GROUND_HEAD = new BukkitStatic(0.25, 0.5);
private static final BukkitShapeModel MODEL_CHEST = new BukkitChest();
private static final BukkitShapeModel MODEL_HONEY_BLOCK = new BukkitStatic(0.0625, 0.9375);
private static final BukkitShapeModel MODEL_SCULK_SHRIEKER = new BukkitStatic(0.0, 0.5);
private static final BukkitShapeModel MODEL_DRIED_GHAST = new BukkitStatic(0.1875f, 0.0f, 0.1875f, 0.8125f, 0.625f, 0.8125f); // NMS bounds: x1,y1,z1,x2,y2,y2 (y2 = 10/16 = 0.625)
private static final BukkitShapeModel MODEL_CONDUIT = new BukkitStatic(
0.33, 0.6875);
private static final BukkitShapeModel MODEL_GROUND_HEAD= new BukkitStatic(
0.25, 0.5); // TODO: XZ-really? 275 ?
private static final BukkitShapeModel MODEL_SINGLE_CHEST = new BukkitStatic(
0.0625, 0.875);
private static final BukkitShapeModel MODEL_HONEY_BLOCK = new BukkitStatic(
0.0625, 0.9375);
// Static blocks with full height sorted by inset.
private static final BukkitShapeModel MODEL_INSET16_1_HEIGHT100 = new BukkitStatic(0.0625, 1.0);
private static final BukkitShapeModel MODEL_INSET16_1_HEIGHT100 = new BukkitStatic(
0.0625, 1.0);
// Static blocks with full xz-bounds sorted by height.
private static final BukkitShapeModel MODEL_XZ100_HEIGHT16_1 = new BukkitStatic(0.0625);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT8_1 = new BukkitStatic(0.125);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT8_3 = new BukkitStatic(0.375);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT16_9 = new BukkitStatic(0.5625);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT4_3 = new BukkitStatic(0.75);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT16_15 = new BukkitDirtLike();
private static final BukkitShapeModel MODEL_XZ100_HEIGHT8_7 = new BukkitStatic(0.875);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT16_1 = new BukkitStatic(
0.0625);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT8_1 = new BukkitStatic(
0.125);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT8_3 = new BukkitStatic(
0.375);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT16_9 = new BukkitStatic(
0.5625);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT4_3 = new BukkitStatic(
0.75);
private static final BukkitShapeModel MODEL_XZ100_HEIGHT16_15 = new BukkitStatic(
0.9375);
/*
* TODO:
* CONDUIT
*/
public MCAccessBukkitModern() {
super();
@@ -141,15 +155,14 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
this.reflectBase = new ReflectBase();
this.reflectDamageSource = new ReflectDamageSource(this.reflectBase);
this.reflectLivingEntity = new ReflectLivingEntity(this.reflectBase, null, this.reflectDamageSource);
// Can be null
this.reflectDamageSources = new ReflectDamageSources(this.reflectBase, this.reflectDamageSource);
}
catch (ClassNotFoundException ex) {}
} catch(ClassNotFoundException ex) {
}
}
@Override
public String getMCVersion() {
return "1.13-26";
return "1.13-1.17|?";
}
@Override
@@ -164,53 +177,33 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
@Override
public void setupBlockProperties(final WorldConfigProvider<?> worldConfigProvider) {
/*
* TODO: Incomplete blocks bounds still use workarounds(not affect movement):
* All fences, glass pane, iron bar, chorus plant, hopper
*
* Legacy blocks still use workarounds(not affect movement):
* All fences, glass pane, iron bar, chorus plant, hopper, cauldron
*
* Scaffolding(affect fall dmg)
*
*/
// Variables for repeated flags (Temporary flags, these should be fixed later so that they are not added here)
final long blockFix = BlockFlags.SOLID_GROUND;
// Adjust flags for individual blocks.
BlockFlags.setBlockFlags(Material.COCOA, blockFix);
BlockFlags.setBlockFlags(Material.TURTLE_EGG, blockFix);
BlockFlags.setBlockFlags(Material.CHORUS_PLANT, blockFix);
BlockFlags.setBlockFlags(Material.CREEPER_WALL_HEAD, blockFix);
BlockFlags.setBlockFlags(Material.ZOMBIE_WALL_HEAD, blockFix);
BlockFlags.setBlockFlags(Material.PLAYER_WALL_HEAD, blockFix);
BlockFlags.setBlockFlags(Material.DRAGON_WALL_HEAD, blockFix);
BlockFlags.setBlockFlags(Material.WITHER_SKELETON_WALL_SKULL, blockFix);
BlockFlags.setBlockFlags(Material.SKELETON_WALL_SKULL, blockFix);
// TODO: Also consider removing flags (passable_x4 etc).
// Variables for repeated flags (Temporary flags, these should be fixed later so that they are not added here)
final long blockFix = BlockFlags.SOLID_GROUND;
// Adjust flags for individual blocks.
BlockProperties.setBlockFlags(Material.COCOA, blockFix);
BlockProperties.setBlockFlags(Material.TURTLE_EGG, blockFix);
BlockProperties.setBlockFlags(Material.CHORUS_PLANT, blockFix);
BlockProperties.setBlockFlags(Material.CREEPER_WALL_HEAD, blockFix);
BlockProperties.setBlockFlags(Material.ZOMBIE_WALL_HEAD, blockFix);
BlockProperties.setBlockFlags(Material.PLAYER_WALL_HEAD, blockFix);
BlockProperties.setBlockFlags(Material.DRAGON_WALL_HEAD, blockFix);
BlockProperties.setBlockFlags(Material.WITHER_SKELETON_WALL_SKULL, blockFix);
BlockProperties.setBlockFlags(Material.SKELETON_WALL_SKULL, blockFix);
// Directly keep blocks as is.
for (final Material mat : new Material[] {
BridgeMaterial.COBWEB,
BridgeMaterial.MOVING_PISTON,
Material.SNOW,
Material.BEACON,
Material.VINE,
Material.CHORUS_FLOWER}) {
BridgeMaterial.COBWEB,
BridgeMaterial.MOVING_PISTON,
Material.SNOW,
Material.BEACON,
Material.VINE,
Material.CHORUS_FLOWER
}) {
processedBlocks.add(mat);
}
for (final Material mat : BridgeMaterial.getAllBlocks(
"light", "glow_lichen", "big_dripleaf_stem")) {
processedBlocks.add(mat);
}
// Shelf mushrooms
for (final Material mat : BridgeMaterial.getAllBlocks("shelf_mushroom")) {
addModel(mat, MODEL_AUTO_FETCH);
}
for (Material mat : MaterialUtil.STRAW_BEDS) {
addModel(mat, MODEL_AUTO_FETCH);
}
// Candle
for (Material mat : MaterialUtil.ALL_CANDLES) {
@@ -221,71 +214,36 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
for (Material mat : MaterialUtil.AMETHYST) {
addModel(mat, MODEL_AUTO_FETCH);
}
// Shelves
for (Material mat : MaterialUtil.WOODEN_SHELVES) {
addModel(mat, MODEL_AUTO_FETCH);
}
// new flower, and others
for (Material mat : BridgeMaterial.getAllBlocks(
"azalea", "flowering_azalea",
"sculk_sensor", "frogspawn",
"sniffer_egg", "decorated_pot", "pitcher_crop", "calibrated_sculk_sensor",
"closed_eyeblossom", "open_eyeblossom", "pale_hanging_moss", "resin_clump","cactus_flower",
"short_dry_grass", "tall_dry_grass", "golden_dandelion")) {
addModel(mat, MODEL_AUTO_FETCH);
}
for (final Material mat : BridgeMaterial.getAllBlocks("pale_moss_carpet")) {
addModel(mat, MODEL_AUTO_FETCH);
}
// *WALL* hanging signs have a collision box. Simple hanging signs don't, so they are treated as an ordinary sign.
for (Material mat : MaterialUtil.WALL_HANGING_SIGNS) {
// Only the post has an actual collision box, the rest is all hit box.
addModel(mat, MODEL_AUTO_FETCH);
}
// Stonecutter and legacy chains
for (Material mat : BridgeMaterial.getAllBlocks(
"stonecutter", "chain")) {
addModel(mat, MODEL_AUTO_FETCH_LEGACY);
}
// Modern iron chains
if (BridgeMaterial.IRON_CHAIN != null) {
addModel(BridgeMaterial.IRON_CHAIN, MODEL_AUTO_FETCH);
}
// Copper chains
for (Material mat : MaterialUtil.COPPER_CHAINS) {
addModel(mat, MODEL_AUTO_FETCH_LEGACY);
}
// Copper golem statues.
for (Material mat : MaterialUtil.COPPER_GOLEM_STATUES) {
"azalea", "flowering_azalea",
"big_dripleaf", "sculk_sensor", "pointed_dripstone",
"stonecutter", "chain"
)) {
addModel(mat, MODEL_AUTO_FETCH);
}
// Camp fire
for (Material mat : BridgeMaterial.getAllBlocks(
"campfire", "soul_campfire")) {
"campfire", "soul_campfire"
)) {
addModel(mat, MODEL_CAMPFIRE);
}
// Cauldron
for (Material mat : MaterialUtil.CAULDRON) {
BlockFlags.setBlockFlags(mat, BlockFlags.SOLID_GROUND);
BlockProperties.setBlockFlags(mat, BlockFlags.SOLID_GROUND);
addModel(mat, MODEL_CAULDRON);
}
//Anvil
for (Material mat : new Material[] {
Material.ANVIL,
Material.CHIPPED_ANVIL,
Material.DAMAGED_ANVIL}) {
addModel(mat, MODEL_ANVIL);
Material.ANVIL,
Material.CHIPPED_ANVIL,
Material.DAMAGED_ANVIL
}) {
addModel(mat, MODEL_ANVIL);
}
// Lily pad
@@ -298,7 +256,6 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
addModel(BridgeMaterial.CAKE, MODEL_CAKE);
// End Rod / Lightning Rod.
// Do they actually have the same model? Doesn't the lightning rod have a slightly different box/bulb at the top? <- No, purely visual.
for (Material mat : MaterialUtil.RODS) {
addModel(mat, MODEL_END_ROD);
}
@@ -309,57 +266,57 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
// Ladder
addModel(Material.LADDER, MODEL_LADDER);
// BrewingStand
addModel(Material.BREWING_STAND, MODEL_BREWING_STAND);
// 1/16 inset at full height blocks.
addModel(Material.DRAGON_EGG, MODEL_INSET16_1_HEIGHT100);
addModel(Material.CACTUS, MODEL_HONEY_BLOCK);
// 1/8 height blocks.
// 1/16 inset at full height.
for (Material mat : new Material[] {
BridgeMaterial.REPEATER,
Material.COMPARATOR }) {
Material.CACTUS,
Material.DRAGON_EGG
}) {
addModel(mat, MODEL_INSET16_1_HEIGHT100);
}
// 1/8 height.
for (Material mat : new Material[] {
BridgeMaterial.REPEATER,
Material.COMPARATOR
}) {
addModel(mat, MODEL_XZ100_HEIGHT8_1);
}
// 3/8 height blocks.
// 3/8 height.
for (Material mat : new Material[] {
Material.DAYLIGHT_DETECTOR}) {
Material.DAYLIGHT_DETECTOR
}) {
addModel(mat, MODEL_XZ100_HEIGHT8_3);
}
// 3/4 height blocks.
// 3/4 height.
for (Material mat : new Material[] {
BridgeMaterial.ENCHANTING_TABLE}) {
BridgeMaterial.ENCHANTING_TABLE
}) {
addModel(mat, MODEL_XZ100_HEIGHT4_3);
}
// All candle cakes
for (Material mat : MaterialUtil.ALL_CANDLE_CAKE) {
addModel(mat, MODEL_CANDLE_CAKE);
}
// 7/8 height.
for (Material mat : new Material[] {
Material.SOUL_SAND}) {
addModel(mat, MODEL_XZ100_HEIGHT8_7);
Material.BREWING_STAND
}) {
addModel(mat, MODEL_BREWING_STAND);
}
// 16/15 height, full xz bounds.
for (Material mat : new Material[] {
BridgeMaterial.GRASS_PATH,
BridgeMaterial.FARMLAND}) {
BridgeMaterial.GRASS_PATH, BridgeMaterial.FARMLAND
}) {
addModel(mat, MODEL_XZ100_HEIGHT16_15);
}
// Thin fence: Glass panes, iron bars, copper bars.
// Thin fence: Glass panes, iron bars.
for (final Material mat : MaterialUtil.addBlocks(
MaterialUtil.GLASS_PANES,
BridgeMaterial.IRON_BARS)) {
addModel(mat, MODEL_THIN_FENCE);
}
for (final Material mat : MaterialUtil.COPPER_BARS) {
MaterialUtil.GLASS_PANES, BridgeMaterial.IRON_BARS)) {
addModel(mat, MODEL_THIN_FENCE);
}
@@ -374,12 +331,12 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
}
// Chests.
// TOOD: Might add a facing/directional extension for double chests.
for (Material mat : BridgeMaterial.getAllBlocks(
"chest", "trapped_chest", "ender_chest")) {
addModel(mat, MODEL_CHEST);
}
for (Material mat : MaterialUtil.COPPER_CHESTS) {
addModel(mat, MODEL_CHEST);
"chest", "trapped_chest",
"ender_chest"
)) {
addModel(mat, MODEL_SINGLE_CHEST);
}
// Beds
@@ -394,26 +351,30 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
// Turtle Eggs.
for (Material mat : new Material[] {
Material.TURTLE_EGG}) {
addModel(mat, MODEL_TURTLE_EGG);
Material.TURTLE_EGG
}) {
addModel(mat, MODEL_TURTLE_EGG);
}
// Conduit
for (Material mat : new Material[] {
Material.CONDUIT}) {
addModel(mat, MODEL_CONDUIT);
Material.CONDUIT
}) {
addModel(mat, MODEL_CONDUIT);
}
// Cocoa
for (Material mat : new Material[] {
Material.COCOA}) {
addModel(mat, MODEL_COCOA);
Material.COCOA
}) {
addModel(mat, MODEL_COCOA);
}
// Sea Pickles
for (Material mat : new Material[] {
Material.SEA_PICKLE}) {
addModel(mat, MODEL_SEA_PICKLE);
Material.SEA_PICKLE
}) {
addModel(mat, MODEL_SEA_PICKLE);
}
// Carpets.
@@ -425,10 +386,8 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
for (final Material mat : MaterialUtil.HEADS_GROUND) {
addModel(mat, MODEL_GROUND_HEAD);
}
// Heads on walls.
for (final Material mat : MaterialUtil.HEADS_WALL) {
addModel(mat, MODEL_WALL_HEAD);
addModel(mat, MODEL_WALL_HEAD);
}
// Doors.
@@ -443,131 +402,84 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
// Chorus Plant.
for (Material mat : new Material[] {
Material.CHORUS_PLANT}) {
addModel(mat, MODEL_CHORUS_PLANT);
Material.CHORUS_PLANT
}) {
addModel(mat, MODEL_CHORUS_PLANT);
}
// Lantern.
//Lantern
for (Material mat : BridgeMaterial.getAllBlocks(
"lantern", "soul_lantern")) {
addModel(mat, MODEL_LANTERN);
}
for (Material mat : MaterialUtil.COPPER_LANTERNS) {
"lantern", "soul_lantern"
)) {
addModel(mat, MODEL_LANTERN);
}
// Piston.
// Piston
for (Material mat : BridgeMaterial.getAllBlocks(
"piston", "sticky_piston", "piston_base", "piston_sticky_base")) {
"piston", "sticky_piston", "piston_base", "piston_sticky_base"
)) {
addModel(mat, MODEL_PISTON);
}
// Piston Head.
// Piston Head
addModel(BridgeMaterial.PISTON_HEAD, MODEL_PISTON_HEAD);
// Snow.
addModel(Material.SNOW, MODEL_SNOW);
// Levelled blocks.
for (Material mat : MaterialUtil.WATER) {
// Levelled blocks
for (Material mat : BridgeMaterial.getAllBlocks(
"snow", "water", "lava"
)) {
addModel(mat, MODEL_LEVELLED);
}
for (Material mat : MaterialUtil.LAVA) {
addModel(mat, MODEL_LEVELLED);
}
// All water plants
for (Material mat : MaterialUtil.WATER_PLANTS) {
addModel(mat, MODEL_WATER_PLANTS);
}
// Rails.
// Rails
for (final Material mat : MaterialUtil.RAILS) {
addModel(mat, MODEL_RAIL);
}
// Walls.
// Walls
for (Material mat : MaterialUtil.ALL_WALLS) {
BlockFlags.setBlockFlags(mat, BlockFlags.SOLID_GROUND | BlockFlags.F_VARIABLE);
addModel(mat, MODEL_THICK_FENCE2);
}
// Lectern.
// Lectern
Material mt = BridgeMaterial.getBlock("lectern");
if (mt != null) addModel(mt, MODEL_LECTERN);
// PowderSnow.
mt = BridgeMaterial.getBlock("powder_snow");
if (mt != null) addModel(mt, MODEL_POWDER_SNOW);
// Bamboo.
// Bamboo
mt = BridgeMaterial.getBlock("bamboo");
if (mt != null) addModel(mt, MODEL_BAMBOO);
// Scaffolding
mt = BridgeMaterial.getBlock("scaffolding");
if (mt != null) addModel(mt, MODEL_SCAFFOLDING);
// Dripstone.
mt = BridgeMaterial.getBlock("pointed_dripstone");
if (mt != null) addModel(mt, MODEL_POINTED_DRIPSTONE);
// Sulfur spike
mt = BridgeMaterial.getBlock("sulfur_spike");
if (mt != null) addModel(mt, MODEL_POINTED_DRIPSTONE);
// Bell.
// Bell
mt = BridgeMaterial.getBlock("bell");
if (mt != null) addModel(mt, MODEL_BELL);
// Composter.
// Composter
mt = BridgeMaterial.getBlock("composter");
if (mt != null) addModel(mt, MODEL_COMPOSTER);
// Honey Block.
// Honey Block
mt = BridgeMaterial.getBlock("honey_block");
if (mt != null) addModel(mt, MODEL_HONEY_BLOCK);
// Big DripLeaf.
mt = BridgeMaterial.getBlock("big_dripleaf");
if (mt != null) addModel(mt, MODEL_DRIP_LEAF);
// Grindstone.
mt = BridgeMaterial.getBlock("grindstone");
if (mt != null) addModel(mt, MODEL_GRIND_STONE);
// Sculk Shrieker
mt = BridgeMaterial.getBlock("sculk_shrieker");
if (mt != null) addModel(mt, MODEL_SCULK_SHRIEKER);
// Mud
mt = BridgeMaterial.getBlock("mud");
if (mt != null) addModel(mt, MODEL_XZ100_HEIGHT8_7);
// Heavy core
mt = BridgeMaterial.getBlock("heavy_core");
if (mt != null) addModel(mt, MODEL_GROUND_HEAD);
// Dried ghast
mt = BridgeMaterial.getBlock("dried_ghast");
if (mt != null) addModel(mt, MODEL_DRIED_GHAST);
// Sort to processed by flags.
for (final Material mat : Material.values()) {
final long flags = BlockFlags.getBlockFlags(mat);
final long flags = BlockProperties.getBlockFlags(mat);
// Stairs.
if (BlockFlags.hasAnyFlag(flags, BlockFlags.F_STAIRS)) {
if (BlockFlags.hasAnyFlag(flags, BlockProperties.F_STAIRS)) {
addModel(mat, MODEL_STAIRS);
}
// Fences.
if (BlockFlags.hasAnyFlag(flags, BlockFlags.F_THICK_FENCE)) {
if (BlockFlags.hasAnyFlag(flags, BlockFlags.F_PASSABLE_X4)) {
if (BlockFlags.hasAnyFlag(flags, BlockProperties.F_THICK_FENCE)) {
if (BlockFlags.hasAnyFlag(flags, BlockProperties.F_PASSABLE_X4)) {
// TODO: Perhaps another model flag.
addModel(mat, MODEL_GATE);
}
else addModel(mat, MODEL_THICK_FENCE);
else {
addModel(mat, MODEL_THICK_FENCE);
}
}
}
super.setupBlockProperties(worldConfigProvider);
}
@@ -576,12 +488,12 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
if (this.reflectLivingEntity == null || this.reflectLivingEntity.obcGetHandle == null) {
return null;
}
return ReflectionUtil.invokeMethodNoArgs(this.reflectLivingEntity.obcGetHandle, player);
Object handle = ReflectionUtil.invokeMethodNoArgs(this.reflectLivingEntity.obcGetHandle, player);
return handle;
}
private boolean canDealFallDamage() {
return this.reflectLivingEntity != null && this.reflectLivingEntity.nmsDamageEntity != null
&& (this.reflectDamageSource.nmsFALL != null || this.reflectDamageSources != null);
return this.reflectLivingEntity != null && this.reflectLivingEntity.nmsDamageEntity != null && this.reflectDamageSource.nmsFALL != null;
}
@Override
@@ -593,35 +505,22 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
public void dealFallDamage(Player player, double damage) {
if (canDealFallDamage()) {
Object handle = getHandle(player);
if (handle != null) {
// Direct accessing DamageSource
Object damageSource = this.reflectDamageSource.nmsFALL;
if (damageSource == null) {
// Fail, second attempt
damageSource = this.reflectDamageSources.getDamageSource(handle);
if (damageSource == null) {
// Fail, deal generic damage
BridgeHealth.damage(player, damage);
// Disable class to prevent continuous damage
reflectDamageSources = null;
return;
}
}
ReflectionUtil.invokeMethod(this.reflectLivingEntity.nmsDamageEntity, handle, damageSource, (float) damage);
}
}
else BridgeHealth.damage(player, damage);
if (handle != null)
ReflectionUtil.invokeMethod(this.reflectLivingEntity.nmsDamageEntity, handle, this.reflectDamageSource.nmsFALL, (float) damage);
} else BridgeHealth.damage(player, damage);
}
@Override
public boolean resetActiveItem(Player player) {
if (this.reflectLivingEntity != null && this.reflectLivingEntity.nmsclearActiveItem != null) {
Object handle = getHandle(player);
if (handle != null) {
ReflectionUtil.invokeMethodNoArgs(this.reflectLivingEntity.nmsclearActiveItem, handle);
return true;
}
Object handle = getHandle(player);
if (handle != null) {
ReflectionUtil.invokeMethodNoArgs(this.reflectLivingEntity.nmsclearActiveItem, handle);
return true;
}
}
return false;
}
}
@@ -1,249 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.attribute.AttributeModifier.Operation;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData;
import fr.neatmonster.nocheatplus.compat.AttribUtil;
import fr.neatmonster.nocheatplus.compat.Bridge1_13;
import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
import fr.neatmonster.nocheatplus.utilities.math.MathUtil;
import fr.neatmonster.nocheatplus.utilities.moving.Magic;
public class NSBukkitAttributeAccess implements IAttributeAccess {
public NSBukkitAttributeAccess() {
if (ReflectionUtil.getClass("org.bukkit.attribute.AttributeInstance") == null) {
throw new RuntimeException("Service not available.");
}
}
private int operationToInt(final Operation operation) {
switch (operation) {
case ADD_NUMBER:
return 0;
case ADD_SCALAR:
return 1;
case MULTIPLY_SCALAR_1:
return 2;
default:
throw new RuntimeException("Unknown operation: " + operation);
}
}
/**
* The first modifier with the given id that can be found, or null if none
* is found.
*
* @param attrInst
* @param id
* @return
*/
private AttributeModifier getModifier(final AttributeInstance attrInst, final NamespacedKey id) {
for (final AttributeModifier mod : attrInst.getModifiers()) {
if (id.equals(mod.getKey())) {
return mod;
}
}
return null;
}
private double getMultiplier(final AttributeModifier mod) {
return AttribUtil.getMultiplier(operationToInt(mod.getOperation()), mod.getAmount());
}
@Override
public double getSpeedMultiplier(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.MOVEMENT_SPEED);
final double val = attrInst.getValue() / attrInst.getBaseValue();
final AttributeModifier mod = getModifier(attrInst, AttribUtil.NSID_SPRINT_BOOST);
return mod == null ? val : (val / getMultiplier(mod));
}
@Override
public double getSprintMultiplier(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.MOVEMENT_SPEED);
final AttributeModifier mod = getModifier(attrInst, AttribUtil.NSID_SPRINT_BOOST);
return mod == null ? 1.0 : getMultiplier(mod);
}
@Override
public float getMovementSpeed(final Player player) {
// / by 2 to get the base value 0.1f
return (player.getWalkSpeed() / 2f) * (float) getSpeedMultiplier(player);
}
@Override
public double getGravity(final Player player) {
double gravity;
if (!BridgeMisc.hasGravity(player)) {
return 0.0;
}
final PlayerMoveData thisMove = DataManager.getPlayerData(player).getGenericInstance(MovingData.class).playerMoves.getCurrentMove();
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.GRAVITY);
// Fail-safe.
if (attrInst == null) {
gravity = thisMove.yDistance <= 0.0 && !Double.isInfinite(Bridge1_13.getSlowfallingAmplifier(player)) ? Magic.SLOW_FALL_GRAVITY : Magic.DEFAULT_GRAVITY;
}
else gravity = MathUtil.clamp(attrInst.getValue(), -1.0, 1.0);
if (thisMove.yDistance <= 0.0 && !Double.isInfinite(Bridge1_13.getSlowfallingAmplifier(player))) {
gravity = Math.min(gravity, Magic.SLOW_FALL_GRAVITY);
}
return gravity;
}
@Override
public double getSafeFallDistance(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.SAFE_FALL_DISTANCE);
// Fail-safe
if (attrInst == null) return Magic.FALL_DAMAGE_DIST;
return MathUtil.clamp(attrInst.getValue(), -1024.0, 1024.0);
}
@Override
public double getFallDamageMultiplier(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.FALL_DAMAGE_MULTIPLIER);
// Fail-safe
if (attrInst == null) return 1.0;
return MathUtil.clamp(attrInst.getValue(), 1.0, 100.0);
}
@Override
public double getBreakingSpeedMultiplier(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.BLOCK_BREAK_SPEED);
// Fail-safe
if (attrInst == null) return 1.0;
return MathUtil.clamp(attrInst.getValue(), 1.0, 1024.0);
}
@Override
public double getJumpGainMultiplier(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.JUMP_STRENGTH);
// Fail-safe
if (attrInst == null) return 1.0;
// Convert it to a multiplier, because we use our own handling for jumping motion.
final double toMultiplier = attrInst.getValue() / attrInst.getBaseValue();
return MathUtil.clamp(toMultiplier, 0.0, 76.19047619047619); // MathUtil.clamp(attrInst.getValue(), 0.0, 32.0);
}
@Override
public double getPlayerSneakingFactor(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.SNEAKING_SPEED);
// Fail-safe.
if (attrInst == null) return Magic.SNEAK_MULTIPLIER + BridgeEnchant.getSwiftSneakIncrement(player);
return MathUtil.clamp(attrInst.getValue(), 0.0, 1.0);
}
@Override
public double getPlayerMaxBlockReach(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.INTERACTION_RANGE);
// Fail-safe
if (attrInst == null) return 4.5;
return MathUtil.clamp(attrInst.getValue(), 0.0, 64.0);
}
@Override
public double getPlayerMaxAttackReach(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.ATTACK_RANGE);
// Fail-safe
if (attrInst == null) return 3.0;
return MathUtil.clamp(attrInst.getValue(), 0.0, 64.0);
}
@Override
public double getMaxStepUp(final Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.STEP_HEIGHT);
if (attrInst == null) {
// Fail-safe.
if (player.isInsideVehicle()) {
if (player.getVehicle() != null && MaterialUtil.isBoat(player.getVehicle().getType())) {
return 0.0;
}
return 1.0;
}
final MovingConfig cc = DataManager.getPlayerData(player).getGenericInstance(MovingConfig.class);
return cc.sfStepHeight;
}
return MathUtil.clamp(attrInst.getValue(), 0.0, 10.0);
}
@Override
public float getMovementEfficiency(Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.MOVEMENT_EFFICIENCY);
// Fail-safe.
if (attrInst == null) return 0.0f;
return (float) MathUtil.clamp(attrInst.getValue(), 0.0, 1.0);
}
@Override
public float getWaterMovementEfficiency(Player player) {
final IPlayerData pData = DataManager.getPlayerData(player);
if (pData.getClientVersion().isLowerThan(ClientVersion.V_1_8)) {
// Doesn't exist.
return 0f;
}
final float depthStrider = BridgeEnchant.getDepthStriderLevel(player);
if (pData.getClientVersion().isLowerThan(ClientVersion.V_1_21)) {
// Use the legacy method.
return depthStrider;
}
if (ServerVersion.isLowerThan("1.21")) {
// Simulate what ViaVersion does for newer (1.21 clients) on older (1.21-) servers.
return depthStrider / 3.0f;
}
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.WATER_MOVEMENT_EFFICIENCY);
if (attrInst == null) return 0.0f;
return (float) MathUtil.clamp(attrInst.getValue(), 0.0f, 1.0f);
}
@Override
public double getSubmergedMiningSpeedMultiplier(Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.SUBMERGED_MINING_SPEED);
// Fail-safe.
if (attrInst == null) return 1.0;
return MathUtil.clamp(attrInst.getValue(), 0.0, 20.0);
}
@Override
public double getMiningEfficiency(Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.MINING_EFFICIENCY);
// Fail-safe.
if (attrInst == null) return 0.0;
return MathUtil.clamp(attrInst.getValue(), 0.0, 1024.0);
}
@Override
public double getEntityScale(Player player) {
final AttributeInstance attrInst = player.getAttribute(BridgeAttribute.SCALE);
// Fail-safe.
if (attrInst == null) return 1.0;
return MathUtil.clamp(attrInst.getValue(), 0.0625, 16.0);
}
}
@@ -35,7 +35,8 @@ public abstract class AbstractBukkitCentered implements BukkitShapeModel {
private final double length;
protected final boolean invertFace;
public AbstractBukkitCentered(double inset, double length, boolean invertFace) {
public AbstractBukkitCentered(double inset, double length,
boolean invertFace) {
// TODO: Might add a signature to specify minY and maxY (attach NWSE only).
this.minDist = inset;
this.maxDist = 1.0 - inset;
@@ -46,44 +47,47 @@ public abstract class AbstractBukkitCentered implements BukkitShapeModel {
protected abstract BlockFace getFacing(BlockData blockData);
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
final BlockFace facing = invertFace ? getFacing(blockData).getOppositeFace() : getFacing(blockData);
// TODO: Evaluate if (some) faces need to be inverted.
// End rod facing: the direction it points to.
switch (facing) {
case EAST:
return new double[] {0.0, minDist, minDist, length, maxDist, maxDist};
case WEST:
return new double[] {1.0 - length, minDist, minDist, 1.0, maxDist, maxDist};
case SOUTH:
return new double[] {minDist, minDist, 0.0, maxDist, maxDist, length};
case NORTH:
return new double[] {minDist, minDist, 1.0 - length, maxDist, maxDist, 1.0};
case DOWN:
return new double[] {minDist, 1.0 - length, minDist, maxDist, 1.0, maxDist};
case UP:
return new double[] {minDist, 0.0, minDist, maxDist, length, maxDist};
default:
break;
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
final BlockFace facing = invertFace
? getFacing(blockData).getOppositeFace()
: getFacing(blockData);
// TODO: Evaluate if (some) faces need to be inverted.
// End rod facing: the direction it points to.
switch (facing) {
case EAST:
return new double[] {0.0, minDist, minDist,
length, maxDist, maxDist};
case WEST:
return new double[] {1.0 - length, minDist, minDist,
1.0, maxDist, maxDist};
case SOUTH:
return new double[] {minDist, minDist, 0.0,
maxDist, maxDist, length};
case NORTH:
return new double[] {minDist, minDist, 1.0 - length,
maxDist, maxDist, 1.0};
case DOWN:
return new double[] {minDist, 1.0 - length, minDist,
maxDist, 1.0, maxDist};
case UP:
return new double[] {minDist, 0.0, minDist,
maxDist, length, maxDist};
default:
break;
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -20,60 +20,48 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitAnvil implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getBlockData();
final IPlayerData data = blockCache.getPlayerData();
final boolean legacy = data != null && data.getClientVersion().isLowerThan(ClientVersion.V_1_13);
if (blockData instanceof Directional) {
BlockFace face = ((Directional) blockData).getFacing();
switch (face) {
case NORTH:
case SOUTH:
if (legacy) return new double[] {0.125, 0.0, 0.0, 0.875, 1.0, 1.0};
return new double[] {
// Bottom
0.125, 0.0, 0.125, 0.875, 0.25, 0.875,
// Top
0.1875, 0.625, 0.0, 0.8125, 1.0, 1.0
// Body... maybe not need
};
case WEST:
case EAST:
if (legacy) return new double[] {0.0, 0.0, 0.125, 1.0, 1.0, 0.875};
return new double[] {
// Bottom
0.125, 0.0, 0.125, 0.875, 0.25, 0.875,
// Top
0.0, 0.625, 0.1875, 1.0, 1.0, 0.8125
// Body... maybe not need
};
default:
break;
case NORTH:
case SOUTH:
return new double[] {
// Bottom
0.125, 0.0, 0.125, 0.875, 0.25, 0.875,
// Top
0.1875, 0.625, 0.0, 0.8125, 1.0, 1.0
// Body... maybe not need
};
case WEST:
case EAST:
return new double[] {
// Bottom
0.125, 0.0, 0.125, 0.875, 0.25, 0.875,
// Top
0.0, 0.625, 0.1875, 1.0, 1.0, 0.8125
// Body... maybe not need
};
default:
break;
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -14,63 +14,39 @@
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import org.bukkit.World;
import java.text.DecimalFormat;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Bamboo;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitBamboo implements BukkitShapeModel {
//private DecimalFormat df = new DecimalFormat("#.000");
//private final double xz = 0.375;
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
if (blockCache.getPlayerData() != null && blockCache.getPlayerData().isBedrockPlayer()) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getBlockData();
if (blockData instanceof Bamboo) {
Bamboo b = (Bamboo) blockData;
double thickness = 0.125;
if (b.getAge() > 0) thickness += 0.0625;
long a = LocUtil.randomSeedBedrock(x, 0, z);
long a1 = a * 2863311531L;
long rdx = (a1 >> 32) & 0xFFFFFFFFL;
//long rax = a1 & 0xFFFFFFFFL;
rdx >>=3;rdx *=3;
rdx = (rdx << 2) & 0xFFFFFFFFL;
double xOffset = a - rdx + 1;
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
a >>=8;
long a2 = a;
a *= 2863311531L;
rdx = (a >> 32) & 0xFFFFFFFFL;
rdx >>=3;rdx *=3;
rdx = (rdx << 2) & 0xFFFFFFFFL;
double zOffset = a2 - rdx +1;
xOffset *= 0.0625;
zOffset *= 0.0625;
return new double[] {xOffset, 0, zOffset, xOffset + thickness, 1.0, zOffset + thickness};
}
}
long i = LocUtil.randomSeedJava(x, 0, z);
final double xOffset = (((i & 15L) / 15.0F) - 0.5D) * 0.5D;
final double zOffset = (((i >> 8 & 15L) / 15.0F) - 0.5D) * 0.5D;
return new double[] {0.40625 + xOffset, 0.0, 0.40625 + zOffset, 0.59375 + xOffset, 1.0, 0.59375 + zOffset};
//final Block block = world.getBlockAt(x, y, z);
//double minX = Math.abs(block.getBoundingBox().getMinX()) - Math.abs((int) block.getBoundingBox().getMinX());
//double minZ = Math.abs(block.getBoundingBox().getMinZ()) - Math.abs((int) block.getBoundingBox().getMinZ());
//minX = Double.parseDouble(df.format(minX));
//minZ = Double.parseDouble(df.format(minZ));
//return new double[] {1.0 - minX + 0.09, 0.0, minZ + 0.09, 1.0 - minX + xz - 0.09, 1.0, minZ + xz - 0.09}; (1)
//return new double[] {minX + 0.09, 0.0, 1.0 - minZ + 0.09, minX + xz - 0.09, 1.0, 1.0 - minZ + xz - 0.09}; (2)
// (1) + (2) =>
//return new double[] {1.0 - minX + 0.09, 0.0, 1.0 - minZ + 0.09, 1.0 - minX + xz - 0.09, 1.0, 1.0 - minZ + xz - 0.09};
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -25,94 +25,91 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitBell implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getBlockData();
if (blockData instanceof Bell) {
Bell b = (Bell) blockData;
BlockFace face = b.getFacing();
switch (b.getAttachment()) {
case CEILING:
return new double[] {0.25, 1 - 0.75, 0.25, 0.75, 1.0, 0.75};
case CEILING: return new double[] {0.25, 1-0.75, 0.25, 0.75, 1.0, 0.75};
case DOUBLE_WALL:
switch (face) {
case NORTH:
case SOUTH:
return new double[] {
case NORTH:
case SOUTH:
return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick hold the bell
0.4375, 0.8125, 0.0, 0.5625, 0.9375, 1.0
//0.0, 0.8125, 0.4375, 1.0, 0.9375, 0.5625
};
case WEST:
case EAST:
return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick holding the bell
0.4375, 0.8125, 0.0, 0.5625, 0.9375, 1.0
//0.0, 0.8125, 0.4375, 1.0, 0.9375, 0.5625
};
case WEST:
case EAST:
return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick holding the bell
// Stick hold the bell
0.0, 0.8125, 0.4375, 1.0, 0.9375, 0.5625
};
default:
break;
default:
break;
}
break;
case FLOOR:
switch (face) {
case NORTH:
case SOUTH:
return new double[] {0.0, 0.0, 0.25, 1.0, 1.0, 0.75};
case WEST:
case EAST:
return new double[] {0.25, 0.0, 0.0, 0.75, 1.0, 1.0};
default:
break;
case NORTH:
case SOUTH:
return new double[] {0.0, 0.0, 0.25, 1.0, 1.0, 0.75};
case WEST:
case EAST:
return new double[] {0.25, 0.0, 0.0, 0.75, 1.0, 1.0};
default:
break;
}
break;
case SINGLE_WALL:
switch (face) {
case NORTH:
return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick holding the bell
0.4375, 0.8125, 0.0, 0.5625, 0.9375, 0.8125
};
case SOUTH:
return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick holding the bell
0.4375, 0.8125, 0.1875, 0.5625, 0.9375, 1.0
};
case WEST:
return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick holding the bell
0.0, 0.8125, 0.4375, 0.8125, 0.9375, 0.5625
};
case EAST:
return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick holding the bell
0.1875, 0.8125, 0.4375, 1.0, 0.9375, 0.5625
};
default:
break;
case NORTH: return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick hold the bell
0.4375, 0.8125, 0.0, 0.5625, 0.9375, 0.8125
};
case SOUTH: return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick hold the bell
0.4375, 0.8125, 0.1875, 0.5625, 0.9375, 1.0
};
case WEST: return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick hold the bell
0.0, 0.8125, 0.4375, 0.8125, 0.9375, 0.5625
};
case EAST: return new double[] {
// Bottom bell
0.25, 0.25, 0.25, 0.75, 0.375, 0.75,
// Body
0.3125, 0.375, 0.3125, 0.6875, 0.8125, 0.6875,
// Stick hold the bell
0.1875, 0.8125, 0.4375, 1.0, 0.9375, 0.5625
};
default:
break;
}
}
}
@@ -120,17 +117,9 @@ public class BukkitBell implements BukkitShapeModel {
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -26,14 +26,15 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitCake implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
if (Bridge1_13.hasBoundingBox()) {
BoundingBox bd = block.getBoundingBox();
return new double[] {bd.getMinX()-x, bd.getMinY()-y, bd.getMinZ()-z, bd.getMaxX()-x, bd.getMaxY()-y, bd.getMaxZ()-z};
}
final BlockData blockData = block.getState().getBlockData();
if (blockData instanceof Cake) {
final Cake cake = (Cake) blockData;
return new double[] {0.0625 + cake.getBites() * 0.125, 0.0, 0.0625, 0.9375, 0.5, 0.9375};
@@ -42,17 +43,9 @@ public class BukkitCake implements BukkitShapeModel {
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -16,32 +16,13 @@ package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitCauldron implements BukkitShapeModel {
private final static double[] new1_13_2Bounds = {
0.0, 0.0, 0.0, 0.125, 1.0, 0.25,
0.0, 0.0, 0.75, 0.125, 1.0, 1.0,
0.125, 0.0, 0.0, 0.25, 1.0, 0.125,
0.125, 0.0, 0.875, 0.25, 1.0, 1.0,
0.75, 0.0, 0.0, 1.0, 1.0, 0.125,
0.75, 0.0, 0.875, 1.0, 1.0, 1.0,
0.875, 0.0, 0.125, 1.0, 1.0, 0.25,
0.875, 0.0, 0.75, 1.0, 1.0, 0.875,
0.0, 0.1875, 0.25, 1.0, 0.25, 0.75,
0.125, 0.1875, 0.125, 0.875, 0.25, 0.25,
0.125, 0.1875, 0.75, 0.875, 0.25, 0.875,
0.25, 0.1875, 0.0, 0.75, 1.0, 0.125,
0.25, 0.1875, 0.875, 0.75, 1.0, 1.0,
0.0, 0.25, 0.25, 0.125, 1.0, 0.75,
0.875, 0.25, 0.25, 1.0, 1.0, 0.75};
private final static double[] new1_13Bounds = makeCauldron(0.1875, 0.125, 0.8125, 0.0625);
private final static double[] legacyBounds = makeCauldron(0.0, 0.125, 1.0, 0.3125);
private final double[] bounds;
private static double[] makeCauldron(double minY, double sideWidth, double sideHeight, double coreHeight) {
return new double[] {
public BukkitCauldron(double minY, double sideWidth, double sideHeight, double coreHeight) {
bounds = new double[] {
// Core
sideWidth, minY, sideWidth, 1 - sideWidth, minY + coreHeight, 1 - sideWidth,
// 4 side
@@ -54,15 +35,7 @@ public class BukkitCauldron implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
IPlayerData pData = blockCache.getPlayerData();
if (pData != null) {
if (pData.getClientVersion().isLowerThan(ClientVersion.V_1_13)) {
return legacyBounds;
} else if (pData.getClientVersion().isLowerThan(ClientVersion.V_1_13_2)) {
return new1_13Bounds;
} else return new1_13_2Bounds;
}
return new1_13Bounds;
return bounds;
}
@Override
@@ -70,15 +43,4 @@ public class BukkitCauldron implements BukkitShapeModel {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return new double[] {0.0, 0.1875, 0.0, 1.0, 1.0, 1.0};
//return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
// Should be true , but current implementation of Visible check of NCP can't do complex ray-trace for performance wise and technical limitations
return false;
}
}
}
@@ -1,99 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Chest;
import org.bukkit.block.data.type.Chest.Type;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitChest implements BukkitShapeModel {
//TODO: With/without this, NCP still throw false when nearby doubled chest. Something else was wrong. Do note flags are correct too: (CHEST / SOLID+GROUND) BlockProps(2.5 / ToolProps(AXE/WOOD) / [3750, 1900, 950, 750, 600, 450, 400])
private final double[] NORTH_AABB = new double[] {0.0625, 0.0, 0.0, 0.9375, 0.875, 0.9375};
private final double[] SOUTH_AABB = new double[] {0.0625, 0.0, 0.0625, 0.9375, 0.875, 1.0};
private final double[] WEST_AABB = new double[] {0.0, 0.0, 0.0625, 0.9375, 0.875, 0.9375};
private final double[] EAST_AABB = new double[] {0.0625, 0.0, 0.0625, 1.0, 0.875, 0.9375};
private final double[] SINGLE = new double[] {0.0625, 0.0, 0.0625, 0.9375, 0.875, 0.9375};
public static BlockFace getConnectedDirection(BlockFace facing, Type chestType) {
return chestType == Type.LEFT ? getClockWise(facing) : getCounterClockWise(facing);
}
public static BlockFace getCounterClockWise(BlockFace dir) {
switch (dir) {
case NORTH: return BlockFace.WEST;
case SOUTH: return BlockFace.EAST;
case WEST: return BlockFace.SOUTH;
case EAST: return BlockFace.NORTH;
default: throw new IllegalStateException("Unable to get CCW facing of " + dir);
}
}
public static BlockFace getClockWise(BlockFace dir) {
switch (dir) {
case NORTH: return BlockFace.EAST;
case SOUTH: return BlockFace.WEST;
case WEST: return BlockFace.NORTH;
case EAST: return BlockFace.SOUTH;
default: throw new IllegalStateException("Unable to get Y-rotated facing of " + dir);
}
}
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Chest) {
final Chest chest = (Chest) blockData;
final Type chestType = chest.getType();
if (chestType == Type.SINGLE) {
return SINGLE;
}
switch (getConnectedDirection(chest.getFacing(), chestType)) {
case NORTH:
default:
return NORTH_AABB;
case SOUTH:
return SOUTH_AABB;
case WEST:
return WEST_AABB;
case EAST:
return EAST_AABB;
}
}
return SINGLE;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
}
@@ -14,10 +14,6 @@
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -26,117 +22,56 @@ import org.bukkit.block.data.MultipleFacing;
import org.bukkit.util.BoundingBox;
import fr.neatmonster.nocheatplus.compat.Bridge1_13;
import fr.neatmonster.nocheatplus.utilities.collision.AxisAlignedBBUtils;
import fr.neatmonster.nocheatplus.utilities.collision.ShapeUtils;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitChorusPlant implements BukkitShapeModel {
private static final BlockFace[] directions = new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN};
private static final double[][] modernShapes = makeShapes();
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
// Server is 1.13.2 higher
if (Bridge1_13.hasBuiltInRayTracing()) {
double[] res = {};
for (BoundingBox box : block.getCollisionShape().getBoundingBoxes()) {
res = ShapeUtils.add(res, AxisAlignedBBUtils.toArray(box));
}
if (res.length == 0) return null;
return res;
} else {
// Server is 1.13
final BlockData blockData = block.getBlockData();
if (blockData instanceof MultipleFacing) {
final MultipleFacing chorusplant = (MultipleFacing) blockData;
return modernShapes[getAABBIndex(chorusplant.getFaces())];
}
if (Bridge1_13.hasBoundingBox()) {
BoundingBox bd = block.getBoundingBox();
return new double[] {bd.getMinX()-x, 0.1875, bd.getMinZ()-z, bd.getMaxX()-x, bd.getMaxY()-y, bd.getMaxZ()-z};
}
final BlockData blockData = block.getBlockData();
double[] res = new double[] {0.187, 0.188, 0.187, 1.0 - 0.187, 0.8125, 1.0 - 0.187};
if (blockData instanceof MultipleFacing) {
final MultipleFacing chorusplant = (MultipleFacing) blockData;
for (final BlockFace face : chorusplant.getFaces()) {
switch (face) {
//case DOWN:
// res[1]=0.0;
// break;
case UP:
res[4]=1.0;
break;
case SOUTH:
res[5]=1.0;
break;
case NORTH:
res[2]=0.0;
break;
case WEST:
res[0]=0.0;
break;
case EAST:
res[3]=1.0;
break;
default:
break;
}
}
}
return new double[] {0,0,0,1.0,1.0,1.0};
}
private static double[][] makeShapes() {
float min = 0.5F - (float) 0.3125;
float max = 0.5F + (float) 0.3125;
double[] base = {min, min, min, max, max, max};
double[][] cs = new double[directions.length][];
for (int i = 0; i < directions.length; i++) {
BlockFace dir = directions[i];
cs[i] = new double[] {0.5D + Math.min(-(float) 0.3125, (double) dir.getModX() * 0.5D), 0.5D + Math.min(-(float) 0.3125, (double) dir.getModY() * 0.5D), 0.5D + Math.min(-(float) 0.3125, (double) dir.getModZ() * 0.5D),
0.5D + Math.max((float) 0.3125, (double) dir.getModX() * 0.5D), 0.5D + Math.max((float) 0.3125, (double) dir.getModY() * 0.5D), 0.5D + Math.max((float) 0.3125, (double) dir.getModZ() * 0.5D)
};
}
double[][] cs2 = new double[64][];
for (int k = 0; k < 64; k++) {
double[] tmp = base;
for (int j = 0; j < directions.length; j++) {
if ((k & 1 << j) != 0) {
tmp = ShapeUtils.merge(tmp, cs[j]);
}
}
cs2[k] = tmp;
}
return cs2;
}
private Set<BlockFace> getLegacyFaces(BlockCache blockCache, World world, int x, int y, int z) {
Set<BlockFace> faces = new HashSet<>();
Material upBlock = blockCache.getType(x, y+1, z);
Material downBlock = blockCache.getType(x, y-1, z);
Material northBlock = blockCache.getType(x, y, z-1);
Material southBlock = blockCache.getType(x, y, z+1);
Material westBlock = blockCache.getType(x-1, y, z);
Material eastBlock = blockCache.getType(x+1, y, z);
if (downBlock == Material.CHORUS_PLANT || downBlock == Material.END_STONE || downBlock == Material.CHORUS_FLOWER) {
faces.add(BlockFace.DOWN);
}
if (upBlock == Material.CHORUS_PLANT || upBlock == Material.CHORUS_FLOWER) {
faces.add(BlockFace.UP);
}
if (northBlock == Material.CHORUS_PLANT || northBlock == Material.CHORUS_FLOWER) {
faces.add(BlockFace.NORTH);
}
if (southBlock == Material.CHORUS_PLANT || southBlock == Material.CHORUS_FLOWER) {
faces.add(BlockFace.SOUTH);
}
if (westBlock == Material.CHORUS_PLANT || westBlock == Material.CHORUS_FLOWER) {
faces.add(BlockFace.WEST);
}
if (eastBlock == Material.CHORUS_PLANT || eastBlock == Material.CHORUS_FLOWER) {
faces.add(BlockFace.EAST);
}
return faces;
}
private int getAABBIndex(Set<BlockFace> faces) {
int i = 0;
for (int j = 0; j < directions.length; ++j) {
if (faces.contains(directions[j])) {
i |= 1 << j;
}
}
return i;
return res;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -29,78 +29,70 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitCocoa implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
if (Bridge1_13.hasBoundingBox()) {
BoundingBox bd = block.getBoundingBox();
return new double[] {bd.getMinX()-x, bd.getMinY()-y, bd.getMinZ()-z, bd.getMaxX()-x, bd.getMaxY()-y, bd.getMaxZ()-z};
}
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Cocoa && blockData instanceof Directional) {
BlockFace face = ((Directional) blockData).getFacing();
final Cocoa cocoa = (Cocoa) blockData;
switch (cocoa.getAge()) {
case 0: // .625 .4375 .0625 max: .375 .75 .3125
switch (face) {
case NORTH:
return new double[] {0.375, 0.4375, 0.0, 0.625, 0.75, 0.315};
case SOUTH:
return new double[] {0.375, 0.4375, 0.685, 0.625, 0.75, 1.0};
case WEST:
return new double[] {0.0, 0.4375, 0.375, 0.315, 0.75, 0.625};
case EAST:
return new double[] {0.685, 0.4375, 0.375, 1.0, 0.75, 0.625};
default:
break;
case NORTH:
return new double[] {0.375, 0.4375, 0.0, 0.625, 0.75, 0.315};
case SOUTH:
return new double[] {0.375, 0.4375, 0.685, 0.625, 0.75, 1.0};
case WEST:
return new double[] {0.0, 0.4375, 0.375, 0.315, 0.75, 0.625};
case EAST:
return new double[] {0.685, 0.4375, 0.375, 1.0, 0.75, 0.625};
default:
break;
}
break;
case 1: // .6875 .3125 .0625 max: .3125 .75 .4375
switch (face) {
case NORTH:
return new double[] {0.3125, 0.3125, 0.0, 0.6875, 0.75, 0.4375};
case SOUTH:
return new double[] {0.3125, 0.3125, 0.5625, 0.6875, 0.75, 1.0};
case WEST:
return new double[] {0.0, 0.3125, 0.3125, 0.4375, 0.75, 0.6875};
case EAST:
return new double[] {0.5625, 0.3125, 0.3125, 1.0, 0.75, 0.6875};
default:
break;
case NORTH:
return new double[] {0.3125, 0.3125, 0.0, 0.6875, 0.75, 0.4375};
case SOUTH:
return new double[] {0.3125, 0.3125, 0.5625, 0.6875, 0.75, 1.0};
case WEST:
return new double[] {0.0, 0.3125, 0.3125, 0.4375, 0.75, 0.6875};
case EAST:
return new double[] {0.5625, 0.3125, 0.3125, 1.0, 0.75, 0.6875};
default:
break;
}
break;
case 2: // .75 .1875 .0625 max: .25 .75 .5625
switch (face) {
case NORTH:
return new double[] {0.25, 0.1875, 0.0, 0.75, 0.75, 0.5625};
case SOUTH:
return new double[] {0.25, 0.1875, 0.4375, 0.75, 0.75, 1.0};
case WEST:
return new double[] {0.0, 0.1875, 0.25, 0.5625, 0.75, 0.75};
case EAST:
return new double[] {0.4375, 0.1875, 0.25, 1.0, 0.75, 0.75};
default:
break;
case NORTH:
return new double[] {0.25, 0.1875, 0.0, 0.75, 0.75, 0.5625};
case SOUTH:
return new double[] {0.25, 0.1875, 0.4375, 0.75, 0.75, 1.0};
case WEST:
return new double[] {0.0, 0.1875, 0.25, 0.5625, 0.75, 0.75};
case EAST:
return new double[] {0.4375, 0.1875, 0.25, 1.0, 0.75, 0.75};
default:
break;
}
//break; ?
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -1,54 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitComposter implements BukkitShapeModel {
private final double[] bounds;
public BukkitComposter(double minY, double sideWidth, double sideHeight, double coreHeight) {
bounds = new double[] {
// Core
sideWidth, minY, sideWidth, 1 - sideWidth, minY + coreHeight, 1 - sideWidth,
// 4 side
0.0, minY, 0.0, 1.0, minY + sideHeight, sideWidth,
0.0, minY, 1.0 - sideWidth, 1.0, minY + sideHeight, 1.0,
0.0, minY, 0.0, sideWidth, minY + sideHeight, 1.0,
1.0 - sideWidth, minY, 0.0, 1.0, minY + sideHeight, 1.0
};
}
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
return bounds;
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return false;
}
}
@@ -30,6 +30,9 @@ public class BukkitDirectionalCentered extends AbstractBukkitCentered {
if (blockData instanceof Directional) {
return ((Directional) blockData).getFacing();
}
return BlockFace.SELF;
else {
return BlockFace.SELF;
}
}
}
}
@@ -1,51 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
/**
* Grass path and farm land shape model.
*/
public class BukkitDirtLike implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
// Farmland changed the height from 1.10 but too lazy and not many clients on this version. Taking shortcut!
final IPlayerData data = blockCache.getPlayerData();
if (data != null && data.getClientVersion().isLowerThan(ClientVersion.V_1_9)) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
return new double[] {0.0, 0.0, 0.0, 1.0, 0.9375, 1.0};
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -34,7 +34,9 @@ public class BukkitDoor implements BukkitShapeModel {
* @return The block face of the block the door is standing on, indicating
* where the door is.
*/
private static final BlockFace getWhereTheDoorIsFace(final BlockFace facing, final Hinge hinge, final boolean isOpen) {
private static final BlockFace getWhereTheDoorIsFace(
final BlockFace facing, final Hinge hinge,
final boolean isOpen) {
// For idiots:
/*
* Facing: Door is closing the opposite side of the block, so the
@@ -43,6 +45,9 @@ public class BukkitDoor implements BukkitShapeModel {
/*
* Hinge: Looking into the facing direction, hinge is left or right.
*/
// Bukkit.getServer().broadcastMessage("hinge=" + hinge
// + " / facing=" + facing
// + " / open=" + isOpen);
// Let's play north and south:
switch (facing) {
case NORTH:
@@ -50,33 +55,49 @@ public class BukkitDoor implements BukkitShapeModel {
if (hinge == Hinge.LEFT) {
return BlockFace.WEST;
}
return BlockFace.EAST;
else {
return BlockFace.EAST;
}
}
else {
return BlockFace.SOUTH;
}
return BlockFace.SOUTH;
case SOUTH:
if (isOpen) {
if (hinge == Hinge.LEFT) {
return BlockFace.EAST;
}
return BlockFace.WEST;
else {
return BlockFace.WEST;
}
}
else {
return BlockFace.NORTH;
}
return BlockFace.NORTH;
case EAST:
if (isOpen) {
if (hinge == Hinge.LEFT) {
return BlockFace.NORTH;
}
return BlockFace.SOUTH;
else {
return BlockFace.SOUTH;
}
}
else {
return BlockFace.WEST;
}
return BlockFace.WEST;
case WEST:
if (isOpen) {
if (hinge == Hinge.LEFT) {
return BlockFace.SOUTH;
}
return BlockFace.NORTH;
else {
return BlockFace.NORTH;
}
}
else {
return BlockFace.EAST;
}
return BlockFace.EAST;
default:
// Invalid
return BlockFace.SELF;
@@ -87,7 +108,8 @@ public class BukkitDoor implements BukkitShapeModel {
private static final double doorWidthOpen = 0.1875;
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
@@ -95,34 +117,28 @@ public class BukkitDoor implements BukkitShapeModel {
final Door door = (Door) blockData;
final boolean isOpen = door.isOpen();
final double doorWidth = doorWidthOpen; // isOpen ? doorWidthOpen : doorWidthClosed;
switch (getWhereTheDoorIsFace(door.getFacing(), door.getHinge(), isOpen)) {
case NORTH:
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, doorWidth};
case SOUTH:
return new double[] {0.0, 0.0, 1.0 - doorWidth, 1.0, 1.0, 1.0};
case EAST:
return new double[] {1.0 - doorWidth, 0.0, 0.0, 1.0, 1.0, 1.0};
case WEST:
return new double[] {0.0, 0.0, 0.0, doorWidth, 1.0, 1.0};
default:
break;
switch(getWhereTheDoorIsFace(door.getFacing(),
door.getHinge(), isOpen)) {
case NORTH:
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, doorWidth};
case SOUTH:
return new double[] {0.0, 0.0, 1.0 - doorWidth, 1.0, 1.0, 1.0};
case EAST:
return new double[] {1.0 - doorWidth, 0.0, 0.0, 1.0, 1.0, 1.0};
case WEST:
return new double[] {0.0, 0.0, 0.0, doorWidth, 1.0, 1.0};
default:
break;
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -1,61 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.BigDripleaf;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitDripLeaf implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getState().getBlockData();
double[] res = {0.0, 0.6875, 0.0, 1.0, 0.9375, 1.0};
if (blockData instanceof BigDripleaf) {
final BigDripleaf dripLeaf = (BigDripleaf) blockData;
switch(dripLeaf.getTilt()) {
case PARTIAL:
res[4] -= 0.125;
return res;
case NONE:
case UNSTABLE:
return res;
default:
return new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
}
}
return null;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -1,98 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.PointedDripstone;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.math.MathUtil;
public class BukkitDripStone implements BukkitShapeModel {
private static final double[] TIP_MERGE = {0.3125, 0.0, 0.3125, 0.6875, 1.0, 0.6875};
private static final double[] TIP_DOWN = {0.3125, 0.3125, 0.3125, 0.6875, 1.0, 0.6875};
private static final double[] TIP_UP = {0.3125, 0.0, 0.3125, 0.6875, 0.6875, 0.6875};
private static final double[] FRUSTUM = {0.25, 0.0, 0.25, 0.75, 1.0, 0.75};
private static final double[] MIDDLE = {0.1875, 0.0, 0.1875, 0.8125, 1.0, 0.8125};
private static final double[] BASE = {0.125, 0.0, 0.125, 0.875, 1.0, 0.875};
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getBlockData();
if (blockData instanceof PointedDripstone) {
boolean bedrock = blockCache.getPlayerData() != null && blockCache.getPlayerData().isBedrockPlayer();
final long randomseed = bedrock ? LocUtil.randomSeedBedrock(x, 0, z) : LocUtil.randomSeedJava(x, 0, z);
double xOffset = MathUtil.clamp(calcOffset(randomseed, false, bedrock), -0.125, 0.125);
double zOffset = MathUtil.clamp(calcOffset(randomseed, true, bedrock), -0.125, 0.125);
PointedDripstone pds = (PointedDripstone) blockData;
switch (pds.getThickness()) {
case TIP_MERGE:
return offset(TIP_MERGE, xOffset, 0, zOffset);
case TIP:
if (pds.getVerticalDirection() == BlockFace.DOWN) {
return offset(TIP_DOWN, xOffset, 0, zOffset);
} else {
return offset(TIP_UP, xOffset, 0, zOffset);
}
case FRUSTUM:
return offset(FRUSTUM, xOffset, 0, zOffset);
case MIDDLE:
return offset(MIDDLE, xOffset, 0, zOffset);
default:
return offset(BASE, xOffset, 0, zOffset);
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
private float calcOffset(long x, boolean shift, boolean bedrock) {
if (shift) x >>=8;
x &= 0xFL;
float b = x;
if (bedrock) {
b *= 0.0333333f;
b -= 0.25f;
} else {
b /= 15f;
b -= 0.5f;
b *= 0.5f;
}
return b;
}
private double[] offset(double[] input, double x, double y, double z) {
return new double[] {input[0] + x, input[1] + y, input[2] + z, input[3] + x, input[4] + y, input[5] + z};
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -25,33 +25,33 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitEndPortalFrame implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof EndPortalFrame) {
return getShape(((EndPortalFrame) blockData).hasEye());
return ((EndPortalFrame) blockData).hasEye()
? new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0}
: new double[] {0.0, 0.0, 0.0, 1.0, 0.8125, 1.0};
}
else {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof EndPortalFrame) {
return ((EndPortalFrame) blockData).hasEye() ? 0x4 : 0;
}
else {
return 0;
}
}
private double[] getShape(boolean hasEye) {
return hasEye ? new double[] {0.0, 0.0, 0.0, 1.0, 0.8125, 1.0, 0.25, 0.8125, 0.25, 0.75, 1.0, 0.75}
: new double[] {0.0, 0.0, 0.0, 1.0, 0.8125, 1.0};
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -20,142 +20,72 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.util.BoundingBox;
import fr.neatmonster.nocheatplus.compat.Bridge1_13;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.collision.AxisAlignedBBUtils;
import fr.neatmonster.nocheatplus.utilities.collision.ShapeUtils;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitFence implements BukkitShapeModel {
private final double[] northplane;
private final double[] southplane;
private final double[] westplane;
private final double[] eastplane;
private final double[] northplaneB;
private final double[] southplaneB;
private final double[] westplaneB;
private final double[] eastplaneB;
private final double[] fullplane;
private final double[] eastwest;
private final double[] southnorth;
private final double[] baseState;
private final boolean cutEdgeOnLowVersions;
public BukkitFence(double inset, double height, boolean cutEdgeOnLowVersions) {
this(inset, 1.0 - inset, height, cutEdgeOnLowVersions);
private final double minXZ;
private final double maxXZ;
private final double height;
public BukkitFence(double inset, double height) {
this(inset, 1.0 - inset, height);
}
public BukkitFence(double minXZ, double maxXZ, double height, boolean cutEdgeOnLowVersions) {
this.cutEdgeOnLowVersions = cutEdgeOnLowVersions;
this.northplane = new double[] {minXZ, 0.0, 0.0, maxXZ, height, maxXZ};
this.southplane = new double[] {minXZ, 0.0, minXZ, maxXZ, height, 1.0};
this.westplane = new double[] {0.0, 0.0, minXZ, maxXZ, height, maxXZ};
this.eastplane = new double[] {minXZ, 0.0, minXZ, 1.0, height, maxXZ};
this.northplaneB = new double[] {minXZ, 0.0, 0.0, maxXZ, height, maxXZ - 0.0625};
this.southplaneB = new double[] {minXZ, 0.0, minXZ + 0.0625, maxXZ, height, 1.0};
this.westplaneB = new double[] {0.0, 0.0, minXZ, maxXZ - 0.0625, height, maxXZ};
this.eastplaneB = new double[] {minXZ + 0.0625, 0.0, minXZ, 1.0, height, maxXZ};
this.eastwest = ShapeUtils.merge(westplane, eastplane);
this.southnorth = ShapeUtils.merge(southplane, northplane);
this.fullplane = ShapeUtils.add(eastwest, southnorth);
this.baseState = new double[] {minXZ, 0.0, minXZ, maxXZ, height, maxXZ};
public BukkitFence(double minXZ, double maxXZ, double height) {
this.minXZ = minXZ;
this.maxXZ = maxXZ;
this.height = height;
}
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final IPlayerData data = blockCache.getPlayerData();
final boolean cutEdge = data != null && cutEdgeOnLowVersions && data.getClientVersion().isLowerThan(ClientVersion.V_1_9);
// Server is 1.13.2 higher and player not on 1.8
if (Bridge1_13.hasBuiltInRayTracing() && !cutEdge) {
double[] res = {};
for (BoundingBox box : block.getCollisionShape().getBoundingBoxes()) {
res = ShapeUtils.add(res, AxisAlignedBBUtils.toArray(box));
}
if (res.length == 0) return null;
return res;
} else {
boolean east = false;
boolean north = false;
boolean west = false;
boolean south = false;
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof MultipleFacing) {
final MultipleFacing fence = (MultipleFacing) blockData;
for (final BlockFace face : fence.getFaces()) {
switch (face) {
case EAST:
east = true;
break;
case NORTH:
north = true;
break;
case WEST:
west = true;
break;
case SOUTH:
south = true;
break;
default:
break;
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
// 13749998807909
// 86250001192093
// 0.1375, 0.8625
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof MultipleFacing) {
// Note isPassableWorkaround for these (no voxel shapes / multi cuboid yet).
final MultipleFacing fence = (MultipleFacing) blockData;
// TODO: If height > 1.0, check if it needs to be capped, provided relevant.
double[] res = new double[] {minXZ, 0.0, minXZ, maxXZ, height, maxXZ};
for (final BlockFace face : fence.getFaces()) {
switch (face) {
case EAST:
res[3] = 1.0;
break;
case NORTH:
res[2] = 0.0;
break;
case WEST:
res[0] = 0.0;
break;
case SOUTH:
res[5] = 1.0;
break;
default:
break;
}
}
}
if (east && north && west && south) {
return fullplane;
}
double tmp[] = new double[0];
if (east && west) {
tmp = eastwest;
east = west = false;
} else if (south && north) {
tmp = southnorth;
south = north = false;
}
if (south) {
tmp = ShapeUtils.add(tmp, cutEdge && isNextDir(east, north, west, south) ? southplaneB : southplane);
}
if (north) {
tmp = ShapeUtils.add(tmp, cutEdge && isNextDir(east, north, west, south) ? northplaneB : northplane);
}
if (east) {
tmp = ShapeUtils.add(tmp, cutEdge && isNextDir(east, north, west, south) ? eastplaneB : eastplane);
}
if (west) {
tmp = ShapeUtils.add(tmp, cutEdge && isNextDir(east, north, west, south) ? westplaneB : westplane);
}
if (tmp.length == 0) {
tmp = ShapeUtils.add(tmp, cutEdge ? fullplane : baseState);
}
return tmp;
return res;
}
}
private boolean isNextDir(boolean east, boolean north, boolean west, boolean south) {
return (north || south) && (west || east);
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
double a[] = getShape(blockCache, world, x, y, z);
for (int i = 1; i < (int)a.length / 6; i++) a[i*6-2] = 1.0;
return a;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
// TODO: Which one is better, return true and cap the height or return false and fetch twice?
// NOTE: Should be no different as current implementation doesn't do exact ray trace check
return true;
}
}
}
@@ -20,14 +20,6 @@ import org.bukkit.util.BoundingBox;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
/**
* Fetches a single BoundingBox from Bukkit's Block#getBoundingBox().
* Returns a six-element double[] {minX, minY, minZ, maxX, maxY, maxZ}
* relative to the block position (world coords minus the block's x,y,z).
*
* This class returns one bounding box; BukkitFetchableBounds reads the VoxelShape and may return multiple boxes for complex
* collision shapes.
*/
public class BukkitFetchableBound implements BukkitShapeModel {
@Override
@@ -37,18 +29,8 @@ public class BukkitFetchableBound implements BukkitShapeModel {
return new double[] {box.getMinX()-x, box.getMinY()-y, box.getMinZ()-z, box.getMaxX()-x, box.getMaxY()-y, box.getMaxZ()-z};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -1,63 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.VoxelShape;
import fr.neatmonster.nocheatplus.utilities.collision.AxisAlignedBBUtils;
import fr.neatmonster.nocheatplus.utilities.collision.ShapeUtils;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
/**
* Fetches the block's collision VoxelShape and returns one or more bounding boxes
* as a concatenated double[] containing {minX,minY,minZ,maxX,maxY,maxZ} for each
* box. Coordinates are expressed relative to the block position.
*
* Difference from BukkitFetchableBound: this class may return multiple boxes
* (preserving complex/multi-part collision geometry); BukkitFetchableBound
* returns a single BoundingBox from Block#getBoundingBox().
*/
public class BukkitFetchableBounds implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final VoxelShape blockShape = block.getCollisionShape();
double[] res = {};
for (BoundingBox box : blockShape.getBoundingBoxes()) {
res = ShapeUtils.add(res, AxisAlignedBBUtils.toArray(box));
}
if (res.length == 0) return null;
return res;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -40,7 +40,8 @@ public class BukkitGate implements BukkitShapeModel {
}
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
@@ -62,23 +63,17 @@ public class BukkitGate implements BukkitShapeModel {
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Openable) {
return ((Openable) blockData).isOpen() ? 0x4 : 0;
}
return 0;
else {
return 0;
}
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -1,123 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Grindstone;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitGrindStone implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getState().getBlockData();
if (blockData instanceof Grindstone) {
final Grindstone grindstone = (Grindstone) blockData;
final BlockFace facing = grindstone.getFacing();
switch (grindstone.getAttachedFace()) {
case CEILING:
switch (facing) {
case NORTH:
case SOUTH:
return new double[] {0.125, 0.5625, 0.375, 0.25, 1.0, 0.625,
0.75, 0.5625, 0.375, 0.875, 1.0, 0.625,
0.125, 0.1875, 0.3125, 0.25, 0.5625, 0.6875,
0.75, 0.1875, 0.3125, 0.875, 0.5625, 0.6875,
0.25, 0.0, 0.125, 0.75, 0.75, 0.875};
case EAST:
case WEST:
return new double[] {0.375, 0.5625, 0.125, 0.625, 1.0, 0.25,
0.375, 0.5625, 0.75, 0.625, 1.0, 0.875,
0.3125, 0.1875, 0.125, 0.6875, 0.5625, 0.25,
0.3125, 0.1875, 0.75, 0.6875, 0.5625, 0.875,
0.125, 0.0, 0.25, 0.875, 0.75, 0.75};
default:
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
case FLOOR:
switch (facing) {
case NORTH:
case SOUTH:
return new double[] {0.125, 0.0, 0.375, 0.25, 0.4375, 0.625,
0.75, 0.0, 0.375, 0.875, 0.4375, 0.625,
0.125, 0.4375, 0.3125, 0.25, 0.8125, 0.6875,
0.75, 0.4375, 0.3125, 0.875, 0.8125, 0.6875,
0.25, 0.25, 0.125, 0.75, 1.0, 0.875};
case EAST:
case WEST:
return new double[] {0.375, 0.0, 0.125, 0.625, 0.4375, 0.25,
0.375, 0.0, 0.75, 0.625, 0.4375, 0.875,
0.3125, 0.4375, 0.125, 0.6875, 0.8125, 0.25,
0.3125, 0.4375, 0.75, 0.6875, 0.8125, 0.875,
0.125, 0.25, 0.25, 0.875, 1.0, 0.75};
default:
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
case WALL:
switch (facing) {
case NORTH:
return new double[] {0.125, 0.375, 0.4375, 0.25, 0.625, 1.0,
0.75, 0.375, 0.4375, 0.875, 0.625, 1.0,
0.125, 0.3125, 0.1875, 0.25, 0.6875, 0.5625,
0.75, 0.3125, 0.1875, 0.875, 0.6875, 0.5625,
0.25, 0.125, 0.0, 0.75, 0.875, 0.75};
case SOUTH:
return new double[] {0.125, 0.375, 0.0, 0.25, 0.625, 0.4375,
0.75, 0.375, 0.0, 0.875, 0.625, 0.4375,
0.125, 0.3125, 0.4375, 0.25, 0.6875, 0.8125,
0.75, 0.3125, 0.4375, 0.875, 0.6875, 0.8125,
0.25, 0.125, 0.25, 0.75, 0.875, 1.0};
case EAST:
return new double[] {0.0, 0.375, 0.125, 0.5625, 0.625, 0.25,
0.0, 0.375, 0.75, 0.5625, 0.625, 0.875,
0.4375, 0.3125, 0.125, 0.8125, 0.6875, 0.25,
0.4375, 0.3125, 0.75, 0.8125, 0.6875, 0.875,
0.25, 0.125, 0.25, 1.0, 0.875, 0.75};
case WEST:
return new double[] {0.4375, 0.375, 0.125, 1.0, 0.625, 0.25,
0.4375, 0.375, 0.75, 1.0, 0.625, 0.875,
0.1875, 0.3125, 0.125, 0.5625, 0.6875, 0.25,
0.1875, 0.3125, 0.75, 0.5625, 0.6875, 0.875,
0.0, 0.125, 0.25, 0.75, 0.875, 0.75};
default:
break;
}
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
@@ -20,124 +20,108 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitHopper implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
IPlayerData pData = blockCache.getPlayerData();
if (pData != null && pData.getClientVersion().isLowerThan(ClientVersion.V_1_13)) {
return new double[] {
0, 0, 0, 1, 0.625, 1,
0, 0.625, 0, 0.125, 1, 1,
0.875, 0.625, 0, 1, 1, 1,
0, 0.625, 0, 1, 1, 0.125,
0, 0.625, 0.875, 1, 1, 1
};
}
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getBlockData();
if (blockData instanceof Directional) {
Directional b = (Directional) blockData;
BlockFace face = b.getFacing();
switch (face) {
case NORTH:
return new double[] {
case NORTH:
return new double[] {
// Standing inside
0.0, 0.625, 0.0, 1.0, 0.6875, 1.0,
// Middle
0.25, 0.25, 0.25, 0.75, 0.625, 0.75,
// Bottom
0.375, 0.25, 0.0, 0.625, 0.5, 0.25,
// Top
0.0, 0.6875, 0.0, 1.0, 1.0, 1.0
// 4 sides of hopper (top)
0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
//0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
//0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
};
case SOUTH:
return new double[] {
case SOUTH:
return new double[] {
// Standing inside
0.0, 0.625, 0.0, 1.0, 0.6875, 1.0,
// Middle
0.25, 0.25, 0.25, 0.75, 0.625, 0.75,
// Bottom
0.375, 0.25, 0.75, 0.625, 0.5, 1.0,
// Top
0.0, 0.6875, 0.0, 1.0, 1.0, 1.0
// 4 sides of hopper (top)
0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
//0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
//0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
};
case WEST:
return new double[] {
case WEST:
return new double[] {
// Standing inside
0.0, 0.625, 0.0, 1.0, 0.6875, 1.0,
// Middle
0.25, 0.25, 0.25, 0.75, 0.625, 0.75,
// Bottom
0.0, 0.25, 0.375, 0.25, 0.5, 0.625,
// Top
0.0, 0.6875, 0.0, 1.0, 1.0, 1.0
// 4 sides of hopper (top)
0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
//0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
//0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
};
case EAST:
return new double[] {
case EAST:
return new double[] {
// Standing inside
0.0, 0.625, 0.0, 1.0, 0.6875, 1.0,
// Middle
0.25, 0.25, 0.25, 0.75, 0.625, 0.75,
// Bottom
0.75, 0.25, 0.375, 1.0, 0.5, 0.625,
// Top
0.0, 0.6875, 0.0, 1.0, 1.0, 1.0
// 4 sides of hopper (top)
0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
//0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
//0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
};
case DOWN:
return new double[] {
case DOWN:
return new double[] {
// Standing inside
0.0, 0.625, 0.0, 1.0, 0.6875, 1.0,
// Middle
0.25, 0.25, 0.25, 0.75, 0.625, 0.75,
// Bottom
0.375, 0.0, 0.375, 0.625, 0.25, 0.625,
// Top
0.0, 0.6875, 0.0, 1.0, 1.0, 1.0
// 4 sides of hopper (top)
0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 1.0, 1.0, 0.125,
//0.0, 0.6875, 0.875, 1.0, 1.0, 1.0,
//0.0, 0.6875, 0.0, 0.125, 1.0, 1.0,
//0.875, 0.6875, 0.0, 1.0, 1.0, 1.0,
};
default:
break;
default:
break;
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
IPlayerData pData = blockCache.getPlayerData();
if (pData != null && pData.getClientVersion().isLowerThan(ClientVersion.V_1_13)) {
return new double[] {0, 0, 0, 1, 1, 1};
}
return new double[] {0.0, 0.625, 0.0, 1.0, 1.0, 1.0, 0.25, 0.25, 0.25, 0.75, 0.625, 0.75};
//return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return false;
}
}
}
@@ -19,49 +19,38 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.util.BoundingBox;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitLadder implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
BoundingBox box = block.getBoundingBox();
return new double[] {box.getMinX()-x, box.getMinY()-y, box.getMinZ()-z, box.getMaxX()-x, box.getMaxY()-y, box.getMaxZ()-z};
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Directional) {
final Directional ladder = (Directional) blockData;
switch(ladder.getFacing()) {
case EAST:
return 5;
case NORTH:
return 6;
case SOUTH:
return 3;
case WEST:
return 4;
default:
break;
case EAST:
return 5;
case NORTH:
return 6;
case SOUTH:
return 3;
case WEST:
return 4;
default:
break;
}
}
return 0;
}
}
}
@@ -24,32 +24,26 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitLantern implements BukkitShapeModel {
private double xz = 0.3125;
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getBlockData();
if (blockData instanceof Lantern) {
Lantern lantern = (Lantern) blockData;
if (lantern.isHanging())
return new double[] {xz, 0.0625, xz, 1-xz, 0.5, 1-xz, 0.375, 0.5, 0.375, 0.625, 0.625, 0.625};
if (lantern.isHanging()) return new double[] {
xz, 0.0625, xz, 1-xz, 0.5, 1-xz,
0.375, 0.5, 0.375, 0.625, 0.625, 0.625};
}
return new double[] {xz, 0.0, xz, 1.0-xz, 0.4375, 1.0-xz, 0.375, 0.4375, 0.375, 0.625, 0.5625, 0.625};
return new double[] {xz, 0.0, xz, 1.0-xz, 0.4375, 1.0-xz,
0.375, 0.4375, 0.375, 0.625, 0.5625, 0.625};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
}
}
@@ -19,32 +19,15 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Levelled;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Snow;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
public class BukkitLevelled implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block blockAbove = world.getBlockAt(x, y + 1, z);
final BlockData blockDataAbove = blockAbove.getBlockData();
if ((BlockFlags.getBlockFlags(world.getBlockAt(x, y, z).getType()) & BlockFlags.F_WATER) != 0
&& (blockDataAbove instanceof Waterlogged && ((Waterlogged)blockDataAbove).isWaterlogged())) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
return new double[] {0.0, 0.0, 0.0, 1.0, 8 / 9f, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return null;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return false;
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
@@ -52,9 +35,13 @@ public class BukkitLevelled implements BukkitShapeModel {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Snow) {
return ((Snow)blockData).getLayers() - 1;
}
if (blockData instanceof Levelled) {
return ((Levelled)blockData).getLevel();
}
return 0;
}
}
}
@@ -1,50 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
/**
* Water Lily shape model.
*/
public class BukkitLilyPad implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final IPlayerData data = blockCache.getPlayerData();
if (data != null && data.getClientVersion().isLowerThan(ClientVersion.V_1_9)) {
return new double[] {0.0625, 0.0, 0.0625, 0.9375, 0.125, 0.9375};
}
return new double[] {0.0625, 0.0, 0.0625, 0.9375, 0.09375, 0.9375};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
}
@@ -28,7 +28,8 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitPiston implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
if (Bridge1_13.hasBoundingBox()) {
@@ -40,9 +41,7 @@ public class BukkitPiston implements BukkitShapeModel {
double[] res = new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
if (blockData instanceof Piston) {
final Piston piston = (Piston) blockData;
if (!piston.isExtended()) {
return res;
}
if (!piston.isExtended()) return res;
final BlockFace face = piston.getFacing();
switch (face) {
case NORTH:
@@ -72,17 +71,9 @@ public class BukkitPiston implements BukkitShapeModel {
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
}
}
@@ -32,67 +32,52 @@ public class BukkitPistonHead implements BukkitShapeModel {
Directional b = (Directional) blockData;
BlockFace face = b.getFacing();
switch (face) {
case UP:
return new double[] {
// Shaft
0.375, 0.0, 0.375, 0.625, 1.0, 0.625,
// Plank
0.0, 0.75, 0.0, 1.0, 1.0, 1.0
};
case DOWN:
return new double[] {
// Shaft
0.375, 0.0, 0.375, 0.625, 1.0, 0.625,
// Plank
0.0, 0.0, 0.0, 1.0, 0.25, 1.0
};
case NORTH:
return new double[] {
// Shaft
0.375, 0.375, 0.0, 0.625, 0.625, 1.0,
// Plank
0.0, 0.0, 0.0, 1.0, 1.0, 0.25
};
case SOUTH:
return new double[] {
// Shaft
0.375, 0.375, 0.0, 0.625, 0.625, 1.0,
// Plank
0.0, 0.0, 0.75, 1.0, 1.0, 1.0
};
case WEST:
return new double[] {
// Shaft
0.0, 0.375, 0.375, 1.0, 0.625, 0.625,
// Plank
0.0, 0.0, 0.0, 0.25, 1.0, 1.0
};
case EAST:
return new double[] {
// Shaft
0.0, 0.375, 0.375, 1.0, 0.625, 0.625,
// Plank
0.75, 0.0, 0.0, 1.0, 1.0, 1.0
};
default:
break;
case UP: return new double[] {
// Shaft
0.375, 0.0, 0.375, 0.625, 1.0, 0.625,
// Plank
0.0, 0.75, 0.0, 1.0, 1.0, 1.0
};
case DOWN: return new double[] {
// Shaft
0.375, 0.0, 0.375, 0.625, 1.0, 0.625,
// Plank
0.0, 0.0, 0.0, 1.0, 0.25, 1.0
};
case NORTH: return new double[] {
// Shaft
0.375, 0.375, 0.0, 0.625, 0.625, 1.0,
// Plank
0.0, 0.0, 0.0, 1.0, 1.0, 0.25
};
case SOUTH: return new double[] {
// Shaft
0.375, 0.375, 0.0, 0.625, 0.625, 1.0,
// Plank
0.0, 0.0, 0.75, 1.0, 1.0, 1.0
};
case WEST: return new double[] {
// Shaft
0.0, 0.375, 0.375, 1.0, 0.625, 0.625,
// Plank
0.0, 0.0, 0.0, 0.25, 1.0, 1.0
};
case EAST: return new double[] {
// Shaft
0.0, 0.375, 0.375, 1.0, 0.625, 0.625,
// Plank
0.75, 0.0, 0.0, 1.0, 1.0, 1.0
};
default:
break;
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
}
}
@@ -1,58 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitPowderSnow implements BukkitShapeModel {
// Some what behave like ladder
double[] REDUCED_HEIGHT = {0.0, 0.0, 0.0, 1.0, 0.9, 1.0};
double[] FULL_HEIGHT = {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
IPlayerData pData = blockCache.getPlayerData();
if (pData != null) {
MovingData data = pData.getGenericInstance(MovingData.class);
if (data.noFallFallDistance > 2.5) {
return REDUCED_HEIGHT;
} else if (data.lastY > y + 1 - 1e-5 && data.hasLeatherBoots && !pData.isShiftKeyPressed()) {
return FULL_HEIGHT;
}
}
return null;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return FULL_HEIGHT;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return false;
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
}
@@ -40,14 +40,4 @@ public class BukkitRail implements BukkitShapeModel {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
// TODO Hold on, this model doesn't seem right, will fix later
return null;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return false;
}
}
}
@@ -1,123 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Scaffolding;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
/**
* Scaffolding shape model.
*/
public class BukkitScaffolding implements BukkitShapeModel {
// Stable visual shape (top slab + four posts)
private static final double[] STABLE_SHAPE = new double[] {
// top slab: 0,14,0 -> 16,16,16
0.0, 0.875, 0.0, 1.0, 1.0, 1.0,
// post (0..2 x, 0..2 z)
0.0, 0.0, 0.0, 0.125, 1.0, 0.125,
// post (14..16 x, 0..2 z)
0.875, 0.0, 0.0, 1.0, 1.0, 0.125,
// post (0..2 x, 14..16 z)
0.0, 0.0, 0.875, 0.125, 1.0, 1.0,
// post (14..16 x, 14..16 z)
0.875, 0.0, 0.875, 1.0, 1.0, 1.0
};
// Unstable visual shape includes a thin bottom plate plus the stable parts
private static final double[] UNSTABLE_SHAPE = new double[] {
// bottom full thin plate: 0,0,0 -> 16,2,16
0.0, 0.0, 0.0, 1.0, 0.125, 1.0,
// include the stable shape boxes as well
0.0, 0.875, 0.0, 1.0, 1.0, 1.0,
0.0, 0.0, 0.0, 0.125, 1.0, 0.125,
0.875, 0.0, 0.0, 1.0, 1.0, 0.125,
0.0, 0.0, 0.875, 0.125, 1.0, 1.0,
0.875, 0.0, 0.875, 1.0, 1.0, 1.0
};
// Just define ground plate, no need full boxes as Minecraft handle climbable if player within 0.3125 inset to the center, and was handled by NCP somewhere else
private static final double[] BOTTOM_PLATE = new double[] {0.0, 0.0, 0.0, 1.0, 0.125, 1.0};
private static final double[] UPPER_PLATE = new double[] {0.0, 0.875, 0.0, 1.0, 1.0, 1.0};
private static final double[] ALL_PLATE = new double[] {0.0, 0.875, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.125, 1.0};
// (empty box)
private static final double[] NO_COLLISION = null;
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData data = block.getBlockData();
// If the player is above the block and not sneaking, return the stable full shape.
IPlayerData pData = blockCache.getPlayerData();
if (data instanceof Scaffolding) {
Scaffolding scaff = (Scaffolding) data;
if (pData != null) {
MovingData mData = pData.getGenericInstance(MovingData.class);
boolean hasbottom = false;
// If scaffolding has distance != 0 and is bottom, and player is just above or within tolerance return bottom plate collision
if (scaff.getDistance() != 0 && scaff.isBottom()) {
hasbottom = true;
}
// If player was above the block and not sneaking -> stable collision
// Vanilla: return full stable collision only when the entity is above the block AND not descending.
// 'isDescending' in vanilla is actually the entity's "isShiftKeyDown" (sneak) flag, not a vertical-velocity test.
//System.out.println("scf 1 " + mData.lastY + ">" + (y + 1 - 1e-5) + " " + !pData.isShiftKeyPressed() + " " + y);
if (mData.lastY > (y + 1 - 1e-5) // p_56071_.isAbove(Shapes.block(), p_56070_, true)
&& !pData.isShiftKeyPressed()) {
return hasbottom ? ALL_PLATE : UPPER_PLATE;
}
if (hasbottom && mData.lastY > y + 0.125 - 1e-5) {
//System.out.println("scf 2");
return BOTTOM_PLATE;
}
//System.out.println("scf 3");
return NO_COLLISION;
// TODO: This should be the VISUAL shape (aka: hitbox), not the COLLISION shape.
// We need to distinguish shapes from collision shapes in the API.
// return scaff.isBottom() ? UNSTABLE_SHAPE : STABLE_SHAPE;
}
// Shortcut Visible haven't set pData...
return (scaff.getDistance() != 0 && scaff.isBottom()) ? UNSTABLE_SHAPE : STABLE_SHAPE;
}
// Fallback to a full block. Should never happen.
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData data = block.getBlockData();
if (data instanceof Scaffolding) {
Scaffolding scaff = (Scaffolding) data;
return (scaff.getDistance() != 0 && scaff.isBottom()) ? UNSTABLE_SHAPE : STABLE_SHAPE;
}
return null;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return false;
}
}
@@ -27,7 +27,8 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitSeaPickle implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
if (Bridge1_13.hasBoundingBox()) {
BoundingBox bd = block.getBoundingBox();
@@ -55,17 +56,9 @@ public class BukkitSeaPickle implements BukkitShapeModel {
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -16,87 +16,33 @@ package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.ShulkerBox;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.block.Container;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitShulkerBox implements BukkitShapeModel {
double FULL_BLOCK[] = {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
// Base full block
double minX = 0.0, minY = 0.0, minZ = 0.0;
double maxX = 1.0, maxY = 1.0, maxZ = 1.0;
if ((state instanceof ShulkerBox)) {
final ShulkerBox shulker = (ShulkerBox) state;
// Closed shulker. Return full block
if (shulker.getInventory().getViewers().isEmpty()) {
return FULL_BLOCK;
//final BlockData blockData = state.getBlockData();
if (state instanceof Container) {
if (!((Container) state).getInventory().getViewers().isEmpty()) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.5, 1.0};
}
// Facing is stored in BlockData, not in ShulkerBox
BlockFace face = BlockFace.UP;
BlockData data = block.getBlockData();
if (data instanceof Directional) {
face = ((Directional) data).getFacing();
}
// Open shulker: extend 0.5 blocks in facing direction
switch (face) {
case UP:
maxY = 1.5;
break;
case DOWN:
minY = -0.5;
break;
case NORTH:
minZ = -0.5;
break;
case SOUTH:
maxZ = 1.5;
break;
case WEST:
minX = -0.5;
break;
case EAST:
maxX = 1.5;
break;
default:
// Should not happen, but just in case... Treat as UP
maxY = 1.5;
break;
}
}
return new double[]{minX, minY, minZ, maxX, maxY, maxZ};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
}
}
@@ -25,7 +25,8 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitSlab implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
@@ -47,17 +48,9 @@ public class BukkitSlab implements BukkitShapeModel {
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
}
}
@@ -1,71 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Snow;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitSnow implements BukkitShapeModel {
private static final double[][] SNOW_LAYERS = {
null,
{0.0, 0.0, 0.0, 1.0, 0.125, 1.0},
{0.0, 0.0, 0.0, 1.0, 0.250, 1.0},
{0.0, 0.0, 0.0, 1.0, 0.375, 1.0},
{0.0, 0.0, 0.0, 1.0, 0.5, 1.0},
{0.0, 0.0, 0.0, 1.0, 0.625, 1.0},
{0.0, 0.0, 0.0, 1.0, 0.75, 1.0},
{0.0, 0.0, 0.0, 1.0, 0.875, 1.0},
{0.0, 0.0, 0.0, 1.0, 1.0, 1.0}
};
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
// TODO: Backward Handling
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Snow) {
return SNOW_LAYERS[((Snow)blockData).getLayers() - 1];
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Snow) {
return ((Snow)blockData).getLayers() - 1;
}
return 0;
}
}
@@ -14,128 +14,65 @@
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import java.util.stream.IntStream;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.Bisected.Half;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Stairs;
import fr.neatmonster.nocheatplus.utilities.collision.ShapeUtils;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitStairs implements BukkitShapeModel {
// Taken from NMS - StairBlock.java
private final double[] topslabs = new double[] {0.0, 0.5, 0.0, 1.0, 1.0, 1.0};
private final double[] bottomslabs = new double[] {0.0, 0.0, 0.0, 1.0, 0.5, 1.0};
private final double[] octet_nnn = new double[] {0.0, 0.0, 0.0, 0.5, 0.5, 0.5};
private final double[] octet_nnp = new double[] {0.0, 0.0, 0.5, 0.5, 0.5, 1.0};
private final double[] octet_pnn = new double[] {0.5, 0.0, 0.0, 1.0, 0.5, 0.5};
private final double[] octet_pnp = new double[] {0.5, 0.0, 0.5, 1.0, 0.5, 1.0};
private final double[] octet_npn = new double[] {0.0, 0.5, 0.0, 0.5, 1.0, 0.5};
private final double[] octet_npp = new double[] {0.0, 0.5, 0.5, 0.5, 1.0, 1.0};
private final double[] octet_ppn = new double[] {0.5, 0.5, 0.0, 1.0, 1.0, 0.5};
private final double[] octet_ppp = new double[] {0.5, 0.5, 0.5, 1.0, 1.0, 1.0};
private final double[][] top_stairs = makeshape(topslabs, octet_nnn, octet_pnn, octet_nnp, octet_pnp);
private final double[][] bottom_stairs = makeshape(bottomslabs, octet_npn, octet_ppn, octet_npp, octet_ppp);
private final int[] shape_by_state = new int[]{12, 5, 3, 10, 14, 13, 7, 11, 13, 7, 11, 14, 8, 4, 1, 2, 4, 1, 2, 8};
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getState().getBlockData();
if (blockData instanceof Stairs) {
final Stairs stairs = (Stairs) blockData;
final Half half = stairs.getHalf();
switch (half) {
case BOTTOM:
return bottom_stairs[shape_by_state[getShapeStateIndex(stairs)]];
case TOP:
return top_stairs[shape_by_state[getShapeStateIndex(stairs)]];
}
}
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
// TODO: With fake data, this could simply return full bounds.
// final Block block = world.getBlockAt(x, y, z);
// final BlockState state = block.getState();
// final BlockData blockData = state.getBlockData();
//
// if (blockData instanceof Stairs) {
// final Stairs stairs = (Stairs) blockData;
// final Half half = stairs.getHalf();
// //final Shape shape = stairs.getShape();
// // TODO: Refine later, with sub shapes.
// switch (half) {
// case BOTTOM:
// return new double[] {0.0, 0.0, 0.0, 1.0, 0.5, 1.0};
// case TOP:
// return new double[] {0.0, 0.5, 0.0, 1.0, 1.0, 1.0};
// default:
// break;
//
// }
// }
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
//final Block block = world.getBlockAt(x, y, z);
//final BlockState state = block.getState();
//final BlockData blockData = state.getBlockData();
//if (blockData instanceof Bisected) {
// final Bisected stairs = (Bisected) blockData;
// final Half half = stairs.getHalf();
// switch (half) {
// case TOP:
// return 0x4;
// default:
// break;
// }
//}
if (blockData instanceof Bisected) {
final Bisected stairs = (Bisected) blockData;
final Half half = stairs.getHalf();
//final Shape shape = stairs.getShape();
// TODO: Refine later, with sub shapes.
switch (half) {
case TOP:
return 0x4;
default:
break;
}
}
return 0;
}
private double[][] makeshape(double[] slab, double[] octet_nn, double[] octet_pn, double[] octet_np, double[] octet_pp) {
return IntStream
.range(0, 16)
.mapToObj((flags) -> makeStairShape(flags, slab, octet_nn, octet_pn, octet_np, octet_pp))
.toArray(double[][]::new);
}
private double[] makeStairShape(int flags, double[] slab, double[] octet_nn, double[] octet_pn, double[] octet_np, double[] octet_pp) {
double[] res = slab;
if ((flags & 1) != 0) {
res = ShapeUtils.merge(res, octet_nn);
}
if ((flags & 2) != 0) {
res = ShapeUtils.merge(res, octet_pn);
}
if ((flags & 4) != 0) {
res = ShapeUtils.merge(res, octet_np);
}
if ((flags & 8) != 0) {
res = ShapeUtils.merge(res, octet_pp);
}
return res;
}
private int getShapeStateIndex(Stairs stair) {
return stair.getShape().ordinal() * 4 + directionToValue(stair.getFacing());
}
private int directionToValue(BlockFace face) {
switch (face) {
default:
case UP:
case DOWN:
return -1;
case NORTH:
return 2;
case SOUTH:
return 0;
case WEST:
return 1;
case EAST:
return 3;
}
}
}
@@ -23,34 +23,27 @@ public class BukkitStatic implements BukkitShapeModel {
private final double[] bounds;
/**
* Constructs a {@code BukkitStatic} block model with full width (no inset) and the specified height.
* This is typically used for regular blocks that occupy the entire block space in the X and Z axes.
*
* @param height the height of the block, corresponding to the Y axis
* Initialize with the given height and with full xz-bounds.
*
* @param height
*/
public BukkitStatic(double height) {
this(0.0, height);
}
/**
* Constructs a {@code BukkitStatic} block model with a specified inset on the X and Z axes and the given height.
* This is useful for blocks that do not occupy the full width and height of a block.
*
* @param xzInset the inset on the X and Z axes, reducing the block's width and height
* @param height the height of the block, corresponding to the Y axis
* Initialize with the given height and xz-inset.
*
* @param xzInset
* @param height
*/
public BukkitStatic(double xzInset, double height) {
this(xzInset, 0.0, xzInset, 1.0 - xzInset, height, 1.0 - xzInset);
}
/**
* Constructs a {@code BukkitStatic} block model using explicit bounding box values.
* The {@code bounds} array must have a length that is a multiple of six, where each group of six values
* represents the minimum and maximum coordinates for X, Y, and Z ({@code minX, minY, minZ, maxX, maxY, maxZ}).
* This constructor allows for the definition of complex or custom-shaped blocks.
*
* @param bounds the bounding box values, in groups of six for each box: minX, minY, minZ, maxX, maxY, maxZ
* @throws IllegalArgumentException if the length of {@code bounds} is not a multiple of six
* Initialize with the given bounds
*
*/
public BukkitStatic(double ...bounds) {
if (bounds.length % 6 != 0) {
@@ -61,22 +54,15 @@ public class BukkitStatic implements BukkitShapeModel {
}
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return bounds;
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
}
}
@@ -29,14 +29,15 @@ public class BukkitTrapDoor implements BukkitShapeModel {
private static final double openWidth = 0.1875;
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof TrapDoor) {
final TrapDoor trapDoor = (TrapDoor) blockData;
if (trapDoor.isOpen()) {
switch (trapDoor.getFacing()) {
switch(trapDoor.getFacing()) {
case NORTH:
return new double[] {0.0, 0.0, 1.0 - openWidth, 1.0, 1.0, 1.0};
case SOUTH:
@@ -49,24 +50,19 @@ public class BukkitTrapDoor implements BukkitShapeModel {
break;
}
}
return trapDoor.getHalf() == Half.BOTTOM ? new double[] {0.0, 0.0, 0.0, 1.0, closedHeight, 1.0}
: new double[] {0.0, 1.0 - closedHeight, 0.0, 1.0, 1.0, 1.0};
else {
return trapDoor.getHalf() == Half.BOTTOM
? new double[] {0.0, 0.0, 0.0, 1.0, closedHeight, 1.0}
: new double[] {0.0, 1.0 - closedHeight, 0.0, 1.0, 1.0, 1.0};
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
@@ -89,4 +85,4 @@ public class BukkitTrapDoor implements BukkitShapeModel {
}
return 0;
}
}
}
@@ -27,15 +27,16 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitTurtleEgg implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
if (Bridge1_13.hasBoundingBox()) {
BoundingBox bd = block.getBoundingBox();
return new double[] {bd.getMinX()-x, bd.getMinY()-y, bd.getMinZ()-z, bd.getMaxX()-x, bd.getMaxY()-y, bd.getMaxZ()-z};
}
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof TurtleEgg) {
final TurtleEgg egg = (TurtleEgg) blockData;
switch (egg.getEggs()) {
@@ -53,17 +54,9 @@ public class BukkitTurtleEgg implements BukkitShapeModel {
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
}
}
@@ -23,184 +23,108 @@ import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.block.data.type.Wall;
import org.bukkit.util.BoundingBox;
import fr.neatmonster.nocheatplus.compat.Bridge1_13;
import fr.neatmonster.nocheatplus.compat.versions.ClientVersion;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.collision.AxisAlignedBBUtils;
import fr.neatmonster.nocheatplus.utilities.collision.ShapeUtils;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitWall implements BukkitShapeModel {
private final double minXZ;
private final double maxXZ;
private final double height;
private final double sideInset;
private final double[] east;
private final double[] north;
private final double[] west;
private final double[] south;
private final double[] eastB;
private final double[] northB;
private final double[] westB;
private final double[] southB;
private final double[] eastwest;
private final double[] southnorth;
private final double[] baseState;
public BukkitWall(double inset, double height) {
this(inset, height, inset);
this(inset, 1.0 - inset, height, 0.0);
}
public BukkitWall(double inset, double height, double sideInset) {
this(inset, 1.0 - inset, height, sideInset, 1.0 - sideInset);
this(inset, 1.0 - inset, height, sideInset);
}
public BukkitWall(double minXZ, double maxXZ, double height, double minSideXZ, double maxSideXZ) {
east = new double[] {maxXZ, 0.0, minSideXZ, 1.0, height, maxSideXZ};
north = new double[] {minSideXZ, 0.0, 0.0, maxSideXZ, height, minXZ};
west = new double[] {0.0, 0.0, minSideXZ, minXZ, height, maxSideXZ};
south = new double[] {minSideXZ, 0.0, maxXZ, maxSideXZ, height, 1.0};
eastB = new double[] {maxXZ, 0.0, minXZ, 1.0, height, maxXZ};
northB = new double[] {minXZ, 0.0, 0.0, maxXZ, height, minXZ};
westB = new double[] {0.0, 0.0, minXZ, minXZ, height, maxXZ};
southB = new double[] {minXZ, 0.0, maxXZ, maxXZ, height, 1.0};
eastwest = new double[] {0.0, 0.0, minSideXZ, 1.0, height, maxSideXZ};
southnorth = new double[] {minSideXZ, 0.0, 0.0, maxSideXZ, height, 1.0};
baseState = new double[] {minXZ, 0.0, minXZ, maxXZ, height, maxXZ};
public BukkitWall(double minXZ, double maxXZ, double height, double sideInset) {
this.minXZ = minXZ;
this.maxXZ = maxXZ;
this.height = height;
this.sideInset = sideInset;
east = new double[] {maxXZ, 0.0, sideInset, 1.0, height, 1.0 - sideInset};
north = new double[] {sideInset, 0.0, 0.0, 1.0 - sideInset, height, minXZ};
west = new double[] {0.0, 0.0, sideInset, minXZ, height, 1.0 - sideInset};
south = new double[] {sideInset, 0.0, maxXZ, 1.0 - sideInset, height, 1.0};
}
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
// Relevant: https://bugs.mojang.com/browse/MC-9565
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final IPlayerData data = blockCache.getPlayerData();
final boolean legacy = data != null && data.getClientVersion().isLowerThan(ClientVersion.V_1_13);
if (Bridge1_13.hasBuiltInRayTracing() && !legacy) {
double[] res = {};
for (BoundingBox box : block.getCollisionShape().getBoundingBoxes()) {
res = ShapeUtils.add(res, AxisAlignedBBUtils.toArray(box));
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof MultipleFacing) {
final MultipleFacing fence = (MultipleFacing) blockData;
double[] res = new double[] {minXZ, 0.0, minXZ, maxXZ, height, maxXZ};
final Set<BlockFace> a = fence.getFaces();
if (!a.contains(BlockFace.UP) && a.size() == 2) {
if (a.contains(BlockFace.SOUTH)) {
return new double[] {sideInset, 0.0, 0.0, 1.0 - sideInset, height, 1.0};
}
if (a.contains(BlockFace.WEST)) {
return new double[] {0.0, 0.0, sideInset, 1.0, height, 1.0 - sideInset};
}
}
for (final BlockFace face : fence.getFaces()) {
switch (face) {
case EAST:
res = add(res, east);
break;
case NORTH:
res = add(res, north);
break;
case WEST:
res = add(res, west);
break;
case SOUTH:
res = add(res, south);
break;
default:
break;
}
}
if (res.length == 0) return null;
return res;
} else {
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
boolean east = false;
boolean north = false;
boolean west = false;
boolean south = false;
boolean up = false;
if (blockData instanceof MultipleFacing) {
MultipleFacing fence = (MultipleFacing) blockData;
Set<BlockFace> faces = fence.getFaces();
up = faces.contains(BlockFace.UP);
for (final BlockFace face : fence.getFaces()) {
switch (face) {
case EAST:
east = true;
break;
case NORTH:
north = true;
break;
case WEST:
west = true;
break;
case SOUTH:
south = true;
break;
default:
break;
}
} else if (blockData instanceof Wall) {
final Wall wall = (Wall) blockData;
if (wall.isUp()) {
double[] res = new double[] {minXZ, 0.0, minXZ, maxXZ, height, maxXZ};
if (!wall.getHeight(BlockFace.WEST).equals(Wall.Height.NONE)) res = add(res, west);
if (!wall.getHeight(BlockFace.EAST).equals(Wall.Height.NONE)) res = add(res, east);
if (!wall.getHeight(BlockFace.NORTH).equals(Wall.Height.NONE)) res = add(res, north);
if (!wall.getHeight(BlockFace.SOUTH).equals(Wall.Height.NONE)) res = add(res, south);
return res;
} else {
if (!wall.getHeight(BlockFace.WEST).equals(Wall.Height.NONE) && !wall.getHeight(BlockFace.EAST).equals(Wall.Height.NONE)) {
return new double[] {0.0, 0.0, sideInset, 1.0, height, 1.0 - sideInset};
}
}
else if (blockData instanceof Wall) {
final Wall wall = (Wall) blockData;
up = wall.isUp();
if (!wall.getHeight(BlockFace.WEST).equals(Wall.Height.NONE)) {
west = true;
}
if (!wall.getHeight(BlockFace.EAST).equals(Wall.Height.NONE)) {
east = true;
}
if (!wall.getHeight(BlockFace.NORTH).equals(Wall.Height.NONE)) {
north = true;
}
if (!wall.getHeight(BlockFace.SOUTH).equals(Wall.Height.NONE)) {
south = true;
if (!wall.getHeight(BlockFace.NORTH).equals(Wall.Height.NONE) && !wall.getHeight(BlockFace.SOUTH).equals(Wall.Height.NONE)) {
return new double[] {sideInset, 0.0, 0.0, 1.0 - sideInset, height, 1.0};
}
}
if (legacy && east && west && south && north) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.5, 1.0};
}
double tmp[] = new double[0];
if (east && west) {
if (legacy) {
if (south) {
return new double[] {0.0, 0.0, 0.25, 1.0, 1.5, 1.0};
}
if (north) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.5, 0.75};
}
}
tmp = eastwest;
east = west = false;
} else if (south && north) {
if (legacy) {
if (west) {
return new double[] {0.0, 0.0, 0.0, 0.75, 1.5, 1.0};
}
if (east) {
return new double[] {0.25, 0.0, 0.0, 1.0, 1.5, 1.0};
}
}
tmp = southnorth;
south = north = false;
}
if (legacy) {
if (south && west) {return new double[] {0.0, 0.0, 0.25, 0.75, 1.5, 1.0};}
if (south && east) {return new double[] {0.25, 0.0, 0.25, 1.0, 1.5, 1.0};}
if (north && west) {return new double[] {0.0, 0.0, 0.0, 0.75, 1.5, 0.75};}
if (north && east) {return new double[] {0.25, 0.0, 0.0, 1.0, 1.5, 0.75};}
}
if (south) {
tmp = ShapeUtils.add(tmp, legacy ? this.southB : this.south);
}
if (north) {
tmp = ShapeUtils.add(tmp, legacy ? this.northB : this.north);
}
if (east) {
tmp = ShapeUtils.add(tmp, legacy ? this.eastB : this.east);
}
if (west) {
tmp = ShapeUtils.add(tmp, legacy ? this.westB : this.west);
}
if (tmp.length == 0 || up) {
tmp = ShapeUtils.add(tmp, this.baseState);
}
return tmp;
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
double a[] = getShape(blockCache, world, x, y, z);
for (int i = 1; i < (int)a.length / 6; i++) a[i*6-2] = 1.0;
return a;
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
// TODO: Which one is better, return true and cap the height or return false and fetch twice?
// NOTE: Should be no different as current implementation doesn't do exact ray trace check
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
}
private double[] add(final double[] array1, final double[] array2) {
final double[] newArray = new double[array1.length + array2.length];
System.arraycopy(array1, 0, newArray, 0, array1.length);
System.arraycopy(array2, 0, newArray, array1.length, array2.length);
return newArray;
}
}
@@ -25,40 +25,33 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitWallHead implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockData blockData = block.getBlockData();
if (blockData instanceof Directional) {
BlockFace face = ((Directional) blockData).getFacing();
switch (face) {
case NORTH:
return new double[] {0.25, 0.25, 0.5, 0.75, 0.75, 1.0};
case SOUTH:
return new double[] {0.25, 0.25, 0.0, 0.75, 0.75, 0.5};
case WEST:
return new double[] {0.5, 0.25, 0.25, 1.0, 0.75, 0.75};
case EAST:
return new double[] {0.0, 0.25, 0.25, 0.5, 0.75, 0.75};
default:
break;
case NORTH:
return new double[] {0.25, 0.25, 0.5, 0.75, 0.75, 1.0};
case SOUTH:
return new double[] {0.25, 0.25, 0.0, 0.75, 0.75, 0.5};
case WEST:
return new double[] {0.5, 0.25, 0.25, 1.0, 0.75, 0.75};
case EAST:
return new double[] {0.0, 0.25, 0.25, 0.5, 0.75, 0.75};
default:
break;
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(final BlockCache blockCache, final World world, final int x, final int y, final int z) {
public int getFakeData(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
return 0;
}
}
}
@@ -1,50 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitWaterPlant implements BukkitShapeModel {
@Override
public double[] getShape(BlockCache blockCache, World world, int x, int y, int z) {
final Block blockAbove = world.getBlockAt(x, y + 1, z);
final BlockData blockDataAbove = blockAbove.getBlockData();
if (blockDataAbove instanceof Waterlogged && ((Waterlogged)blockDataAbove).isWaterlogged()) {
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
return new double[] {0.0, 0.0, 0.0, 1.0, 8 / 9f, 1.0};
}
@Override
public double[] getVisualShape(BlockCache blockCache, World world, int x, int y, int z) {
return getShape(blockCache, world, x, y, z);
}
@Override
public boolean isCollisionSameVisual(BlockCache blockCache, World world, int x, int y, int z) {
return true;
}
@Override
public int getFakeData(BlockCache blockCache, World world, int x, int y, int z) {
return 0;
}
}
@@ -19,51 +19,10 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public interface ShapeModel<W> {
// TODO: Rather fill in all into node directly (data as well), avoid redundant casting etc.
// TODO: Best route passable workaround through here too (base on a flag), + getGroundMinHeight?.
// TODO: Refine +- might have BukkitBlockCacheNode etc.
/**
* Get the <i>collision</i> shape of the block at the given position. <br>
* <strong> Do note that not all blocks have a collision shape, like all plants/farmable blocks, which do have a visual shape that can be interacted with, but don't have a collision one;
* other have a collision shape that exceeds their visual one, like fences, which have a height of 1.0 block visually, but 1.5 collision-wise and such. </strong> <br>
* Most of the time, the collision shape will be the same as its visual shape, but not always. <br>
* To check for any divergence, use {@link #isCollisionSameVisual(BlockCache, W, int, int, int)}. <br>
*
* @param blockCache The block cache.
* @param world The world.
* @param x The x coordinate of the block.
* @param y The y coordinate of the block.
* @param z The z coordinate of the block.
* @return An array of doubles representing the collision shape, in the format
* {minX, minY, minZ, maxX, maxY, maxZ, ...} for each box in the shape.
* Coordinates are in the range [0.0, 1.0].
*/
public double[] getShape(BlockCache blockCache, W world, int x, int y, int z);
/**
* Tell if collision shape is the same as visual shape <br>
*
* @param blockCache
* @param world
* @param x
* @param y
* @param z
* @return if true
*/
public boolean isCollisionSameVisual(BlockCache blockCache, W world, int x, int y, int z);
/**
* Get the visual shape of the block at the given position. <br>
* Call this method if dealing with visual interactions, like ray tracing for line of sight, block targeting, etc. <br>
* @See {@link #getShape(BlockCache, W, int, int, int)} for collision shape. <br>
*
* @param blockCache
* @param world
* @param x
* @param y
* @param z
* @return
*/
public double[] getVisualShape(BlockCache blockCache, W world, int x, int y, int z);
/**
* Allow faking data.
@@ -17,7 +17,6 @@ package fr.neatmonster.nocheatplus.compat.cbreflect;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.compat.blocks.LegacyBlocks;
import fr.neatmonster.nocheatplus.compat.bukkit.BlockCacheBukkit;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectHelper;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectHelper.ReflectFailureException;
@@ -45,30 +44,8 @@ public class BlockCacheCBReflect extends BlockCacheBukkit {
@Override
public double[] fetchBounds(int x, int y, int z) {
final org.bukkit.Material mat = getType(x, y, z);
final double[] shape = LegacyBlocks.getShape(this, mat, x, y, z, true);
if (shape != null) return shape;
try {
return LegacyBlocks.adjustBounds(this, mat, x, y, z, helper.nmsWorld_fetchBlockShape(this.nmsWorld, this.getType(x, y, z), x, y, z));
}
catch (ReflectFailureException ex) {
return super.fetchBounds(x, y, z);
}
}
@Override
public boolean isCollisionSameVisual(int x, int y, int z) {
final org.bukkit.Material mat = getType(x, y, z);
return LegacyBlocks.isCollisionSameVisual(this, mat, x, y, z);
}
@Override
public double[] fetchVisualBounds(int x, int y, int z) {
final org.bukkit.Material mat = getType(x, y, z);
final double[] shape = LegacyBlocks.getVisualShape(this, mat, x, y, z);
if (shape != null) return shape;
try {
return LegacyBlocks.adjustBounds(this, mat, x, y, z, helper.nmsWorld_fetchBlockShape(this.nmsWorld, this.getType(x, y, z), x, y, z));
return helper.nmsWorld_fetchBlockShape(this.nmsWorld, this.getType(x, y, z), x, y, z);
}
catch (ReflectFailureException ex) {
return super.fetchBounds(x, y, z);
@@ -22,7 +22,7 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.bukkit.BlockCacheBukkit;
import fr.neatmonster.nocheatplus.compat.bukkit.MCAccessBukkit;
import fr.neatmonster.nocheatplus.compat.bukkit.MCAccessBukkitModern;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectHelper;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectHelper.ReflectFailureException;
import fr.neatmonster.nocheatplus.compat.versions.GenericVersion;
@@ -31,7 +31,7 @@ import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class MCAccessCBReflect extends MCAccessBukkit {
public class MCAccessCBReflect extends MCAccessBukkitModern {
protected final ReflectHelper helper;
@@ -49,11 +49,11 @@ public class MCAccessCBReflect extends MCAccessBukkit {
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.INIT, "The Minecraft version could not be detected, Compat-CB-Reflect might or might not work.");
this.knownSupportedVersion = false;
}
else if (GenericVersion.compareVersions(mcVersion, "1.5") < 0) {
else if (GenericVersion.compareVersions(mcVersion, "1.4.5") < 0) {
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.INIT, "The Minecraft version seems to be older than what Compat-CB-Reflect can support.");
this.knownSupportedVersion = false;
}
else if (GenericVersion.compareVersions(mcVersion, "1.12.2") > 0) {
else if (GenericVersion.compareVersions(mcVersion, "1.14.4") > 0) {
this.knownSupportedVersion = false;
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.INIT, "The Minecraft version seems to be more recent than the one Compat-CB-Reflect has been built with - this might work, but there could be incompatibilities.");
} else {
@@ -70,7 +70,8 @@ public class MCAccessCBReflect extends MCAccessBukkit {
@Override
public String getMCVersion() {
return "1.5-1.12.2";
// Potentially all :p.
return "1.7-1.14.4|?";
}
@Override
@@ -20,13 +20,9 @@ import java.util.UUID;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.compat.AttribUtil;
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
import fr.neatmonster.nocheatplus.utilities.moving.Magic;
public class ReflectAttributeAccess implements IAttributeAccess {
@@ -150,7 +146,17 @@ public class ReflectAttributeAccess implements IAttributeAccess {
throw new RuntimeException("Not available.");
}
}
@Override
public double getSpeedAttributeMultiplier(Player player) {
return getSpeedAttributeMultiplier(player, true);
}
@Override
public double getSprintAttributeMultiplier(Player player) {
return nmsAttributeInstance_getSprintAttributeModifierMultiplier(getMovementSpeedAttributeInstance(player));
}
/**
* Get the speed attribute (MOVEMENT_SPEED) for a player.
* @param handle EntityPlayer
@@ -159,9 +165,9 @@ public class ReflectAttributeAccess implements IAttributeAccess {
private Object getMovementSpeedAttributeInstance(Player player) {
return ReflectionUtil.invokeMethod(this.reflectPlayer.nmsGetAttributeInstance, getHandle(player), this.reflectGenericAttributes.nmsMOVEMENT_SPEED);
}
/**
*
*
* @param player
* @param removeSprint If to calculate away the sprint boost modifier.
* @return
@@ -182,7 +188,7 @@ public class ReflectAttributeAccess implements IAttributeAccess {
}
}
}
/**
* (Not an existing method.)
* @param attributeInstance
@@ -196,102 +202,10 @@ public class ReflectAttributeAccess implements IAttributeAccess {
return AttribUtil.getMultiplier((Integer) ReflectionUtil.invokeMethodNoArgs(this.reflectAttributeModifier.nmsGetOperation, mod), (Double) ReflectionUtil.invokeMethodNoArgs(this.reflectAttributeModifier.nmsGetValue, mod));
}
}
private Object getHandle(Player player) {
Object handle = ReflectionUtil.invokeMethodNoArgs(this.reflectPlayer.obcGetHandle, player);
return handle;
}
@Override
public double getSpeedMultiplier(Player player) {
return getSpeedAttributeMultiplier(player, true);
}
@Override
public float getMovementSpeed(final Player player) {
// / by 2 to get the base value 0.1f
return (player.getWalkSpeed() / 2f) * (float) getSpeedMultiplier(player);
}
@Override
public double getSprintMultiplier(Player player) {
return nmsAttributeInstance_getSprintAttributeModifierMultiplier(getMovementSpeedAttributeInstance(player));
}
@Override
public double getGravity(Player player) {
return Magic.DEFAULT_GRAVITY;
}
@Override
public double getSafeFallDistance(Player player) {
return Magic.FALL_DAMAGE_DIST;
}
@Override
public double getFallDamageMultiplier(Player player) {
return 1.0;
}
@Override
public double getBreakingSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getJumpGainMultiplier(Player player) {
return 1.0;
}
@Override
public double getPlayerSneakingFactor(Player player) {
return Magic.SNEAK_MULTIPLIER;
}
@Override
public double getPlayerMaxBlockReach(Player player) {
return 4.5;
}
@Override
public double getPlayerMaxAttackReach(Player player) {
return 3.0;
}
@Override
public double getMaxStepUp(Player player) {
if (player.isInsideVehicle()) {
if (player.getVehicle() != null && MaterialUtil.isBoat(player.getVehicle().getType())) {
return 0.0;
}
return 1.0;
}
final MovingConfig cc = DataManager.getPlayerData(player).getGenericInstance(MovingConfig.class);
return cc.sfStepHeight;
}
@Override
public float getMovementEfficiency(Player player) {
return 0f;
}
@Override
public float getWaterMovementEfficiency(Player player) {
return 0f;
}
@Override
public double getSubmergedMiningSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getMiningEfficiency(Player player) {
return 0f;
}
@Override
public double getEntityScale(Player player) {
return 1.0;
}
}
@@ -17,11 +17,10 @@ package fr.neatmonster.nocheatplus.compat.cbreflect.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.bukkit.Material;
import fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectHelper.ReflectFailureException;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import org.bukkit.Material;
/**
* Reflection for block shape getting (latest).
@@ -14,8 +14,6 @@
*/
package fr.neatmonster.nocheatplus.compat.cbreflect.reflect;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
@@ -57,7 +55,6 @@ public class ReflectBlockSix implements IReflectBlock {
/** (static) */
public final Method nmsGetById;
public final Object nmsById;
public final Method nmsGetMaterial;
public final boolean useBlockPosition;
@@ -78,11 +75,6 @@ public class ReflectBlockSix implements IReflectBlock {
final Class<?> clazz = Class.forName(base.nmsPackageName + ".Block");
// byID (static)
nmsGetById = ReflectionUtil.getMethod(clazz, "getById", int.class);
final Class<?> blockArray = Array.newInstance(clazz, 0).getClass();
final Field byIdField = ReflectionUtil.getField(clazz, "byId", blockArray);
nmsById = byIdField == null ? null : ReflectionUtil.get(byIdField, blockArray, null);
// getMaterial
nmsGetMaterial = ReflectionUtil.getMethodNoArgs(clazz, "getMaterial");
// updateShape
@@ -223,9 +215,6 @@ public class ReflectBlockSix implements IReflectBlock {
@SuppressWarnings("deprecation")
@Override
public Object nms_getByMaterial(final Material id) {
if (this.nmsById != null) {
return Array.get(nmsById, id.getId());
}
if (this.nmsGetById == null) {
fail();
}
@@ -269,7 +258,7 @@ public class ReflectBlockSix implements IReflectBlock {
@Override
public boolean isFetchBoundsAvailable() {
return (nmsGetById != null || nmsById != null) && nmsUpdateShape != null && nmsGetMinX != null;
return nmsGetById != null && nmsUpdateShape != null && nmsGetMinX != null;
}
}
@@ -1,77 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.compat.cbreflect.reflect;
import java.lang.reflect.Method;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
public class ReflectDamageSources {
public Class<?> nmsClass;
public Method nmsDamageSources;
public Method nmsfall;
public ReflectDamageSources(ReflectBase base, ReflectDamageSource reflectDamageSource) throws ClassNotFoundException {
this(base, reflectDamageSource, Class.forName(base.nmsPackageName + ".Entity"));
}
public ReflectDamageSources(ReflectBase base, ReflectDamageSource reflectDamageSource, Class<?> nmsEntityClass) throws ClassNotFoundException {
nmsClass = Class.forName("net.minecraft.world.damagesource.DamageSources");
nmsfall = ReflectionUtil.getMethodNoArgs(nmsClass, "k", reflectDamageSource.nmsClass);
// 1.19 Entity.damageSources()
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "dG", nmsClass);
// 1.20
if (nmsDamageSources == null) {
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "dJ", nmsClass);
}
// 1.20.2
if (nmsDamageSources == null) {
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "dM", nmsClass);
}
// 1.20.4
if (nmsDamageSources == null) {
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "dN", nmsClass);
}
// 1.20.5-1.20.6
if (nmsDamageSources == null) {
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "dQ", nmsClass);
}
// 1.21
if (nmsDamageSources == null) {
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "dP", nmsClass);
nmsfall = ReflectionUtil.getMethodNoArgs(nmsClass, "l", reflectDamageSource.nmsClass);
}
// 1.21.2-1.21.3
if (nmsDamageSources == null) {
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "dX", nmsClass);
nmsfall = ReflectionUtil.getMethodNoArgs(nmsClass, "l", reflectDamageSource.nmsClass);
}
// 1.21.8 and possibly earlier down to .4
if (nmsDamageSources == null) {
nmsDamageSources = ReflectionUtil.getMethodNoArgs(nmsEntityClass, "ea", nmsClass);
// TODO: Check
// nmsfall = ReflectionUtil.getMethodNoArgs(nmsClass, "l", reflectDamageSource.nmsClass);
}
}
public Object getDamageSource(Object handle) {
if (nmsDamageSources == null || nmsfall == null) return null;
Object damageSources = ReflectionUtil.invokeMethodNoArgs(nmsDamageSources, handle);
return ReflectionUtil.invokeMethodNoArgs(nmsfall, damageSources);
}
}
@@ -40,8 +40,6 @@ public class ReflectEntity extends ReflectGetHandleBase<Entity> {
public final Method nmsDamageEntity;
private final Method nmsDamageEntityNew;
@MostlyHarmless()
public final Method nmsclearActiveItem;
@@ -64,17 +62,14 @@ public class ReflectEntity extends ReflectGetHandleBase<Entity> {
nmsDead = ReflectionUtil.getField(nmsClass, "dead", boolean.class);
// damageEntity(...)
// boolean hurt(net.minecraft.world.damagesource.DamageSource,float) -> a
nmsDamageEntityNew = ReflectionUtil.getMethod(nmsClass, "a", new Class<?>[]{damageSource.nmsClass, float.class});
nmsDamageEntity = nmsDamageEntityNew != null ? nmsDamageEntityNew :
ReflectionUtil.getMethod(nmsClass, "damageEntity",
new Class<?>[]{damageSource.nmsClass, float.class}, new Class<?>[]{damageSource.nmsClass, int.class});
nmsDamageEntity = ReflectionUtil.getMethod(nmsClass, "damageEntity",
new Class<?>[]{damageSource.nmsClass, float.class}, new Class<?>[]{damageSource.nmsClass, int.class});
if (nmsDamageEntity != null) {
nmsDamageEntityInt = nmsDamageEntity.getParameterTypes()[1] == int.class;
} else {
nmsDamageEntityInt = true; // Uncertain.
}
nmsclearActiveItem = seekClearActiveItemMethod(nmsClass);
nmsclearActiveItem = ReflectionUtil.getMethodNoArgs(nmsClass, "clearActiveItem");
// getBoundingBox
if (reflectAxisAlignedBB == null) {
@@ -85,25 +80,6 @@ public class ReflectEntity extends ReflectGetHandleBase<Entity> {
}
}
private Method seekClearActiveItemMethod(Class<?> nmsClass) {
// void releaseUsingItem() -> fL (1.21.8 and possibly down to .4)
// fE(1.21.2-1.21.3)
// fw(1.21-1.21.1)
// fA(1.20.5-1.20.6)
// fs(1.20.4)
// fr(1.20.2)
// fn(1.20)
// fj(1.19-19.4)
// eR(???)
// clearActiveItem(1.13-???)
String[] methodname = {"fL", "fE", "fw", "fA", "fs", "fr", "fn", "fj", "eR", "clearActiveItem", "releaseUsingItem"};
for (String name : methodname) {
Method method = ReflectionUtil.getMethodNoArgs(nmsClass, name);
if (method != null) return method;
}
return null;
}
@Override
protected void fail() {
// Unused.
+20 -9
View File
@@ -24,7 +24,7 @@
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatspigotcb1_12_r1</artifactId>
<artifactId>ncpcompatcbdev</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<!-- ... -->
@@ -133,12 +133,23 @@
</dependencies>
</profile>
<profile>
<id>cbdev</id>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcbdev</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>spigot1_12_r1</id>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatspigotcb1_12_r1</artifactId>
<artifactId>ncpcompatcbdev</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
</dependencies>
@@ -210,14 +221,10 @@
</dependencies>
</profile>
<!-- Legacy, unsupported
<profile>
<id>cblegacy</id>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb3100</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb3043</artifactId>
@@ -263,12 +270,16 @@
<artifactId>ncpcompatcb2645</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<!-- Legacy, unsupported
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2602</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb3100</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2545</artifactId>
@@ -279,9 +290,9 @@
<artifactId>ncpcompatcb2512</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
-->
</dependencies>
</profile>
-->
</profiles>
</project>
+40 -28
View File
@@ -1,34 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2645</artifactId>
<packaging>jar</packaging>
<name>NCPCompatCB2645</name>
<version>1.1-SNAPSHOT</version>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatnonfree</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>nocheatplus-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<artifactId>ncpcompatcb2645</artifactId>
<version>1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>NCPCompatCB2645</name>
<description>Compatibility for CB2645 (MC 1.5).</description>
<description>Compatibility for CB 2645 (MC 1.5).
</description>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5-R0.1</version>
<scope>system</scope>
<systemPath>${basedir}/libs/craftbukkit-1.5-R0.1-20130317.180842-21.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
@@ -22,7 +22,6 @@ import org.bukkit.craftbukkit.v1_5_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_5_R1.entity.CraftEntity;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.compat.blocks.LegacyBlocks;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import net.minecraft.server.v1_5_R1.AxisAlignedBB;
import net.minecraft.server.v1_5_R1.EntityBoat;
@@ -110,13 +109,10 @@ public class BlockCacheCB2645 extends BlockCache {
public double[] fetchBounds(final int x, final int y, final int z){
// TODO: change api for this / use nodes (!)
final org.bukkit.Material mat = getType(x, y, z);
@SuppressWarnings("deprecation")
final int id = mat.getId();
final int id = getType(x, y, z).getId();
final net.minecraft.server.v1_5_R1.Block block = net.minecraft.server.v1_5_R1.Block.byId[id];
if (block == null) return null;
final double[] shape = LegacyBlocks.getShape(this, mat, x, y, z, true);
if (shape != null) return shape;
block.updateShape(iBlockAccess, x, y, z); // TODO: use THIS instead of world.
// minX, minY, minZ, maxX, maxY, maxZ
@@ -183,11 +183,6 @@ public class MCAccessCB2645 implements MCAccess {
return AlmostBoolean.NO;
}
@Override
public boolean resetActiveItem(Player player) {
return false;
}
// @Override
// public void correctDirection(final Player player) {
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
+40 -28
View File
@@ -1,34 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2691</artifactId>
<packaging>jar</packaging>
<name>NCPCompatCB2691</name>
<version>1.1-SNAPSHOT</version>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatnonfree</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>nocheatplus-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<artifactId>ncpcompatcb2691</artifactId>
<version>1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5.1-R0.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>NCPCompatCB2691</name>
<description>Compatibility for CB2691 (MC 1.5.1-R0.2 beta release).</description>
<description>Compatibility for CB2691 (1.5.1-R0.1 beta release).
</description>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5.1-R0.2</version>
<scope>system</scope>
<systemPath>${basedir}/libs/craftbukkit-1.5.1-R0.2-SNAPSHOT.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
@@ -22,7 +22,6 @@ import org.bukkit.craftbukkit.v1_5_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_5_R2.entity.CraftEntity;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.compat.blocks.LegacyBlocks;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import net.minecraft.server.v1_5_R2.AxisAlignedBB;
import net.minecraft.server.v1_5_R2.EntityBoat;
@@ -110,13 +109,10 @@ public class BlockCacheCB2691 extends BlockCache {
public double[] fetchBounds(final int x, final int y, final int z){
// TODO: change api for this / use nodes (!)
final org.bukkit.Material mat = getType(x, y, z);
@SuppressWarnings("deprecation")
final int id = mat.getId();
final int id = getType(x, y, z).getId();
final net.minecraft.server.v1_5_R2.Block block = net.minecraft.server.v1_5_R2.Block.byId[id];
if (block == null) return null;
final double[] shape = LegacyBlocks.getShape(this, mat, x, y, z, true);
if (shape != null) return shape;
block.updateShape(iBlockAccess, x, y, z); // TODO: use THIS instead of world.
// minX, minY, minZ, maxX, maxY, maxZ
@@ -185,11 +185,6 @@ public class MCAccessCB2691 implements MCAccess{
return AlmostBoolean.NO;
}
@Override
public boolean resetActiveItem(Player player) {
return false;
}
// @Override
// public void correctDirection(final Player player) {
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
+40 -28
View File
@@ -1,34 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2763</artifactId>
<packaging>jar</packaging>
<name>NCPCompatCB2763</name>
<version>1.1-SNAPSHOT</version>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatnonfree</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>nocheatplus-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<artifactId>ncpcompatcb2763</artifactId>
<version>1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5.2-R1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>NCPCompatCB2763</name>
<description>Compatibility for CB2763 (MC 1.5.2).</description>
<description>Compatibility for CB 2763 (MC 1.5.2).
</description>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5.2-R1.0</version>
<scope>system</scope>
<systemPath>${basedir}/libs/craftbukkit-1.5.2-R1.0.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
@@ -22,7 +22,6 @@ import org.bukkit.craftbukkit.v1_5_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_5_R3.entity.CraftEntity;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.compat.blocks.LegacyBlocks;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import net.minecraft.server.v1_5_R3.AxisAlignedBB;
import net.minecraft.server.v1_5_R3.EntityBoat;
@@ -108,13 +107,11 @@ public class BlockCacheCB2763 extends BlockCache {
@Override
public double[] fetchBounds(final int x, final int y, final int z){
// TODO: change api for this / use nodes (!)
final org.bukkit.Material mat = getType(x, y, z);
final int id = iBlockAccess.getTypeId(x, y, z);
final net.minecraft.server.v1_5_R3.Block block = net.minecraft.server.v1_5_R3.Block.byId[id];
if (block == null) return null;
final double[] shape = LegacyBlocks.getShape(this, mat, x, y, z, true);
if (shape != null) return shape;
block.updateShape(iBlockAccess, x, y, z); // TODO: use THIS instead of world.
// minX, minY, minZ, maxX, maxY, maxZ
@@ -184,11 +184,6 @@ public class MCAccessCB2763 implements MCAccess{
return AlmostBoolean.NO;
}
@Override
public boolean resetActiveItem(Player player) {
return false;
}
// @Override
// public void correctDirection(final Player player) {
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
+40 -28
View File
@@ -1,34 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2794</artifactId>
<packaging>jar</packaging>
<name>NCPCompatCB2794</name>
<version>1.1-SNAPSHOT</version>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatnonfree</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>nocheatplus-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<artifactId>ncpcompatcb2794</artifactId>
<version>1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>NCPCompatCB2794</name>
<description>Compatibility for CB2794 (MC 1.6.1).</description>
<description>Compatibility for CB 2794 (MC 1.6.1).
</description>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.1-R0.1</version>
<scope>system</scope>
<systemPath>${basedir}/libs/craftbukkit-1.6.1-R0.1-SNAPSHOT.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
@@ -23,10 +23,6 @@ import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import net.minecraft.server.v1_6_R1.AttributeInstance;
import net.minecraft.server.v1_6_R1.AttributeModifier;
import net.minecraft.server.v1_6_R1.GenericAttributes;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.utilities.moving.Magic;
public class AttributeAccess implements IAttributeAccess {
@@ -37,106 +33,25 @@ public class AttributeAccess implements IAttributeAccess {
}
@Override
public double getSpeedMultiplier(Player player) {
public double getSpeedAttributeMultiplier(Player player) {
final AttributeInstance attr = ((CraftLivingEntity) player).getHandle().a(GenericAttributes.d);
double val = attr.e() / attr.b();
final AttributeModifier mod = attr.a(AttribUtil.ID_SPRINT_BOOST);
if (mod == null) {
return val;
}
else {
} else {
return val / AttribUtil.getMultiplier(mod.c(), mod.d());
}
}
@Override
public float getMovementSpeed(final Player player) {
// / by 2 to get the base value 0.1f
return (player.getWalkSpeed() / 2f) * (float) getSpeedMultiplier(player);
}
@Override
public double getSprintMultiplier(Player player) {
public double getSprintAttributeMultiplier(Player player) {
final AttributeModifier mod = ((CraftLivingEntity) player).getHandle().a(GenericAttributes.d).a(AttribUtil.ID_SPRINT_BOOST);
if (mod == null) {
return 1.0;
}
else {
} else {
return AttribUtil.getMultiplier(mod.c(), mod.d());
}
}
////////////////////////////////////////////////////////////////
// Modern attributes. Not available for legacy versions. //
////////////////////////////////////////////////////////////////
@Override
public double getGravity(Player player) {
return Magic.DEFAULT_GRAVITY;
}
@Override
public double getSafeFallDistance(Player player) {
return Magic.FALL_DAMAGE_DIST;
}
@Override
public double getFallDamageMultiplier(Player player) {
return 1.0;
}
@Override
public double getBreakingSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getJumpGainMultiplier(Player player) {
return 1.0;
}
@Override
public double getPlayerSneakingFactor(Player player) {
return Magic.SNEAK_MULTIPLIER;
}
@Override
public double getPlayerMaxBlockReach(Player player) {
return 4.5;
}
@Override
public double getPlayerMaxAttackReach(Player player) {
return 3.0;
}
@Override
public double getMaxStepUp(Player player) {
final MovingConfig cc = DataManager.getPlayerData(player).getGenericInstance(MovingConfig.class);
return cc.sfStepHeight;
}
@Override
public float getMovementEfficiency(Player player) {
return 0.0f;
}
@Override
public float getWaterMovementEfficiency(Player player) {
return 0.0f;
}
@Override
public double getSubmergedMiningSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getMiningEfficiency(Player player) {
return 0.0;
}
@Override
public double getEntityScale(Player player) {
return 1.0;
}
}
@@ -22,7 +22,6 @@ import org.bukkit.craftbukkit.v1_6_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_6_R1.entity.CraftEntity;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.compat.blocks.LegacyBlocks;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import net.minecraft.server.v1_6_R1.AxisAlignedBB;
import net.minecraft.server.v1_6_R1.EntityBoat;
@@ -110,13 +109,10 @@ public class BlockCacheCB2794 extends BlockCache {
public double[] fetchBounds(final int x, final int y, final int z){
// TODO: change api for this / use nodes (!)
final org.bukkit.Material mat = getType(x, y, z);
@SuppressWarnings("deprecation")
final int id = mat.getId();
final int id = getType(x, y, z).getId();
final net.minecraft.server.v1_6_R1.Block block = net.minecraft.server.v1_6_R1.Block.byId[id];
if (block == null) return null;
final double[] shape = LegacyBlocks.getShape(this, mat, x, y, z, true);
if (shape != null) return shape;
block.updateShape(iBlockAccess, x, y, z);
// minX, minY, minZ, maxX, maxY, maxZ
+40 -28
View File
@@ -1,34 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2808</artifactId>
<packaging>jar</packaging>
<name>NCPCompatCB2808</name>
<version>1.1-SNAPSHOT</version>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatnonfree</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>nocheatplus-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<artifactId>ncpcompatcb2808</artifactId>
<version>1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.2-R1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>NCPCompatCB2808</name>
<description>Compatibility for CB2808 (MC 1.6.2).</description>
<description>Compatibility for CB2808 (MC 1.6.2).
</description>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.2-R0.1</version>
<scope>system</scope>
<systemPath>${basedir}/libs/craftbukkit-1.6.2-R0.1-SNAPSHOT.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
@@ -23,9 +23,6 @@ import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import net.minecraft.server.v1_6_R2.AttributeInstance;
import net.minecraft.server.v1_6_R2.AttributeModifier;
import net.minecraft.server.v1_6_R2.GenericAttributes;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.utilities.moving.Magic;
public class AttributeAccess implements IAttributeAccess {
@@ -36,107 +33,25 @@ public class AttributeAccess implements IAttributeAccess {
}
@Override
public double getSpeedMultiplier(Player player) {
public double getSpeedAttributeMultiplier(Player player) {
final AttributeInstance attr = ((CraftLivingEntity) player).getHandle().getAttributeInstance(GenericAttributes.d);
final double val = attr.getValue() / attr.b();
final AttributeModifier mod = attr.a(AttribUtil.ID_SPRINT_BOOST);
if (mod == null) {
return val;
}
else {
} else {
return val / AttribUtil.getMultiplier(mod.c(), mod.d());
}
}
@Override
public float getMovementSpeed(final Player player) {
// / by 2 to get the base value 0.1f
return (player.getWalkSpeed() / 2f) * (float) getSpeedMultiplier(player);
}
@Override
public double getSprintMultiplier(Player player) {
public double getSprintAttributeMultiplier(Player player) {
final AttributeModifier mod = ((CraftLivingEntity) player).getHandle().getAttributeInstance(GenericAttributes.d).a(AttribUtil.ID_SPRINT_BOOST);
if (mod == null) {
return 1.0;
}
else {
} else {
return AttribUtil.getMultiplier(mod.c(), mod.d());
}
}
////////////////////////////////////////////////////////////////
// Modern attributes. Not available for legacy versions. //
////////////////////////////////////////////////////////////////
@Override
public double getGravity(Player player) {
return Magic.DEFAULT_GRAVITY;
}
@Override
public double getSafeFallDistance(Player player) {
return Magic.FALL_DAMAGE_DIST;
}
@Override
public double getFallDamageMultiplier(Player player) {
return 1.0;
}
@Override
public double getBreakingSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getJumpGainMultiplier(Player player) {
return 1.0;
}
@Override
public double getPlayerSneakingFactor(Player player) {
return Magic.SNEAK_MULTIPLIER;
}
@Override
public double getPlayerMaxBlockReach(Player player) {
return 4.5;
}
@Override
public double getPlayerMaxAttackReach(Player player) {
return 3.0;
}
@Override
public double getMaxStepUp(Player player) {
final MovingConfig cc = DataManager.getPlayerData(player).getGenericInstance(MovingConfig.class);
return cc.sfStepHeight;
}
@Override
public float getMovementEfficiency(Player player) {
return 0.0f;
}
@Override
public float getWaterMovementEfficiency(Player player) {
return 0.0f;
}
@Override
public double getSubmergedMiningSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getMiningEfficiency(Player player) {
return 0.0;
}
@Override
public double getEntityScale(Player player) {
return 1.0;
}
}
@@ -22,7 +22,6 @@ import org.bukkit.craftbukkit.v1_6_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_6_R2.entity.CraftEntity;
import org.bukkit.entity.Entity;
import fr.neatmonster.nocheatplus.compat.blocks.LegacyBlocks;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import net.minecraft.server.v1_6_R2.AxisAlignedBB;
import net.minecraft.server.v1_6_R2.EntityBoat;
@@ -110,13 +109,10 @@ public class BlockCacheCB2808 extends BlockCache {
public double[] fetchBounds(final int x, final int y, final int z){
// TODO: change api for this / use nodes (!)
final org.bukkit.Material mat = getType(x, y, z);
@SuppressWarnings("deprecation")
final int id = mat.getId();
final int id = getType(x, y, z).getId();
final net.minecraft.server.v1_6_R2.Block block = net.minecraft.server.v1_6_R2.Block.byId[id];
if (block == null) return null;
final double[] shape = LegacyBlocks.getShape(this, mat, x, y, z, true);
if (shape != null) return shape;
block.updateShape(iBlockAccess, x, y, z); // TODO: use THIS instead of world.
// minX, minY, minZ, maxX, maxY, maxZ
+40 -28
View File
@@ -1,34 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatcb2882</artifactId>
<packaging>jar</packaging>
<name>NCPCompatCB2882</name>
<version>1.1-SNAPSHOT</version>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcompatnonfree</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>fr.neatmonster</groupId>
<artifactId>nocheatplus-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<artifactId>ncpcompatcb2882</artifactId>
<version>1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>NCPCompatCB2882</name>
<description>Compatibility for CB2882 (MC 1.6.4).</description>
<description>Compatibility for CB2882 (MC 1.6.4).
</description>
<dependencies>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>ncpcore</artifactId>
<version>1.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.4-R2.0</version>
<scope>system</scope>
<systemPath>${basedir}/libs/craftbukkit-1.6.4-R2.0.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
@@ -23,9 +23,6 @@ import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import net.minecraft.server.v1_6_R3.AttributeInstance;
import net.minecraft.server.v1_6_R3.AttributeModifier;
import net.minecraft.server.v1_6_R3.GenericAttributes;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.utilities.moving.Magic;
public class AttributeAccess implements IAttributeAccess {
@@ -36,107 +33,25 @@ public class AttributeAccess implements IAttributeAccess {
}
@Override
public double getSpeedMultiplier(Player player) {
public double getSpeedAttributeMultiplier(Player player) {
final AttributeInstance attr = ((CraftLivingEntity) player).getHandle().getAttributeInstance(GenericAttributes.d);
final double val = attr.getValue() / attr.b();
final AttributeModifier mod = attr.a(AttribUtil.ID_SPRINT_BOOST);
if (mod == null) {
return val;
}
else {
} else {
return val / AttribUtil.getMultiplier(mod.c(), mod.d());
}
}
@Override
public float getMovementSpeed(final Player player) {
// / by 2 to get the base value 0.1f
return (player.getWalkSpeed() / 2f) * (float) getSpeedMultiplier(player);
}
@Override
public double getSprintMultiplier(Player player) {
public double getSprintAttributeMultiplier(Player player) {
final AttributeModifier mod = ((CraftLivingEntity) player).getHandle().getAttributeInstance(GenericAttributes.d).a(AttribUtil.ID_SPRINT_BOOST);
if (mod == null) {
return 1.0;
}
else {
} else {
return AttribUtil.getMultiplier(mod.c(), mod.d());
}
}
////////////////////////////////////////////////////////////////
// Modern attributes. Not available for legacy versions. //
////////////////////////////////////////////////////////////////
@Override
public double getGravity(Player player) {
return Magic.DEFAULT_GRAVITY;
}
@Override
public double getSafeFallDistance(Player player) {
return Magic.FALL_DAMAGE_DIST;
}
@Override
public double getFallDamageMultiplier(Player player) {
return 1.0;
}
@Override
public double getBreakingSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getJumpGainMultiplier(Player player) {
return 1.0;
}
@Override
public double getPlayerSneakingFactor(Player player) {
return Magic.SNEAK_MULTIPLIER;
}
@Override
public double getPlayerMaxBlockReach(Player player) {
return 4.5;
}
@Override
public double getPlayerMaxAttackReach(Player player) {
return 3.0;
}
@Override
public double getMaxStepUp(Player player) {
final MovingConfig cc = DataManager.getPlayerData(player).getGenericInstance(MovingConfig.class);
return cc.sfStepHeight;
}
@Override
public float getMovementEfficiency(Player player) {
return 0.0f;
}
@Override
public float getWaterMovementEfficiency(Player player) {
return 0.0f;
}
@Override
public double getSubmergedMiningSpeedMultiplier(Player player) {
return 1.0;
}
@Override
public double getMiningEfficiency(Player player) {
return 0.0;
}
@Override
public double getEntityScale(Player player) {
return 1.0;
}
}
Loaded 100 of 483 files, more files were not shown because too many files have changed in this diff. Show more