Towards vehicles with multiple passengers.
This commit is contained in:
parent
f7a11bbc95
commit
30c3a40622
|
@ -0,0 +1,24 @@
|
|||
package fr.neatmonster.nocheatplus.compat.bukkit;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.entity.IEntityAccessVehicle;
|
||||
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
|
||||
|
||||
public class EntityAccessVehicleMultiPassenger implements IEntityAccessVehicle {
|
||||
|
||||
public EntityAccessVehicleMultiPassenger() {
|
||||
// TODO: List<Entity>
|
||||
if (ReflectionUtil.getMethodNoArgs(Entity.class, "getPassengers", List.class) == null) {
|
||||
throw new RuntimeException("Not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Entity> getEntityPassengers(final Entity entity) {
|
||||
return entity.getPassengers();
|
||||
}
|
||||
|
||||
}
|
|
@ -50,6 +50,8 @@ import fr.neatmonster.nocheatplus.checks.combined.Combined;
|
|||
import fr.neatmonster.nocheatplus.checks.combined.Improbable;
|
||||
import fr.neatmonster.nocheatplus.compat.Bridge1_9;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
|
||||
import fr.neatmonster.nocheatplus.components.entity.IEntityAccessVehicle;
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
|
||||
import fr.neatmonster.nocheatplus.components.registry.feature.JoinLeaveListener;
|
||||
import fr.neatmonster.nocheatplus.stats.Counters;
|
||||
import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
|
||||
|
@ -85,6 +87,8 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
|
|||
private final int idIllegalItem = counters.registerKey("illegalitem");
|
||||
private final int idEggOnEntity = counters.registerKey("eggonentity");
|
||||
|
||||
private final IGenericInstanceHandle<IEntityAccessVehicle> handleVehicles = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstanceHandle(IEntityAccessVehicle.class);
|
||||
|
||||
public InventoryListener() {
|
||||
super(CheckType.INVENTORY);
|
||||
}
|
||||
|
@ -414,10 +418,18 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
|
|||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onEntityPortal(final EntityPortalEnterEvent event) {
|
||||
final Player player = InventoryUtil.getPlayerPassengerRecursively(event.getEntity());
|
||||
if (player != null) {
|
||||
// Note: ignore cancelother setting.
|
||||
open.check(player);
|
||||
// Check passengers flat for now.
|
||||
final Entity entity = event.getEntity();
|
||||
if (entity instanceof Player) {
|
||||
open.check((Player) entity);
|
||||
}
|
||||
else {
|
||||
for (final Entity passenger : handleVehicles.getHandle().getEntityPassengers(entity)) {
|
||||
if (passenger instanceof Player) {
|
||||
// Note: ignore cancelother setting.
|
||||
open.check((Player) passenger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package fr.neatmonster.nocheatplus.compat.bukkit;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.entity.IEntityAccessVehicle;
|
||||
|
||||
/**
|
||||
* Legacy access to vehicle entities (single passenger only).
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class EntityAccessVehicleLegacy implements IEntityAccessVehicle {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public List<Entity> getEntityPassengers(final Entity entity) {
|
||||
return Arrays.asList(entity.getPassenger());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package fr.neatmonster.nocheatplus.components.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
/**
|
||||
* Vehicle specific access to entities.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface IEntityAccessVehicle {
|
||||
|
||||
/**
|
||||
* Get the current passengers for a vehicle (entity).
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
public List<Entity> getEntityPassengers(Entity entity);
|
||||
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
package fr.neatmonster.nocheatplus.utilities;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
@ -32,26 +31,26 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
|
|||
*
|
||||
*/
|
||||
public class InventoryUtil {
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Does not account for special slots like armor.
|
||||
*
|
||||
* @param inventory
|
||||
* the inventory
|
||||
* @return the free slots
|
||||
*/
|
||||
public static int getFreeSlots(final Inventory inventory) {
|
||||
final ItemStack[] contents = inventory.getContents();
|
||||
int count = 0;
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
if (BlockProperties.isAir(contents[i])) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static int getFreeSlots(final Inventory inventory) {
|
||||
final ItemStack[] contents = inventory.getContents();
|
||||
int count = 0;
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
if (BlockProperties.isAir(contents[i])) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Count slots with type-id and data (enchantments and other meta data are
|
||||
* ignored at present).
|
||||
*
|
||||
|
@ -61,26 +60,26 @@ public class InventoryUtil {
|
|||
* the reference
|
||||
* @return the stack count
|
||||
*/
|
||||
public static int getStackCount(final Inventory inventory, final ItemStack reference) {
|
||||
if (inventory == null) return 0;
|
||||
if (reference == null) return getFreeSlots(inventory);
|
||||
final Material mat = reference.getType();
|
||||
final int durability = reference.getDurability();
|
||||
final ItemStack[] contents = inventory.getContents();
|
||||
int count = 0;
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
final ItemStack stack = contents[i];
|
||||
if (stack == null) {
|
||||
continue;
|
||||
}
|
||||
else if (stack.getType() == mat && stack.getDurability() == durability) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static int getStackCount(final Inventory inventory, final ItemStack reference) {
|
||||
if (inventory == null) return 0;
|
||||
if (reference == null) return getFreeSlots(inventory);
|
||||
final Material mat = reference.getType();
|
||||
final int durability = reference.getDurability();
|
||||
final ItemStack[] contents = inventory.getContents();
|
||||
int count = 0;
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
final ItemStack stack = contents[i];
|
||||
if (stack == null) {
|
||||
continue;
|
||||
}
|
||||
else if (stack.getType() == mat && stack.getDurability() == durability) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sum of bottom + top inventory slots with item type / data, see:
|
||||
* getStackCount(Inventory, reference).
|
||||
*
|
||||
|
@ -90,55 +89,29 @@ public class InventoryUtil {
|
|||
* the reference
|
||||
* @return the stack count
|
||||
*/
|
||||
public static int getStackCount(final InventoryView view, final ItemStack reference) {
|
||||
return getStackCount(view.getBottomInventory(), reference) + getStackCount(view.getTopInventory(), reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for players / passengers (broken by name: closes the inventory of
|
||||
* first player found including entity and passengers recursively).
|
||||
*
|
||||
* @param entity
|
||||
* the entity
|
||||
* @return true, if successful
|
||||
*/
|
||||
public static boolean closePlayerInventoryRecursively(Entity entity) {
|
||||
// Find a player.
|
||||
final Player player = getPlayerPassengerRecursively(entity);
|
||||
if (player != null && closeOpenInventory((Player) entity)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player from an entity. This will return the first player found
|
||||
* amongst the entity itself and passengers checked recursively.
|
||||
*
|
||||
* @param entity
|
||||
* the entity
|
||||
* @return the player passenger recursively
|
||||
*/
|
||||
public static Player getPlayerPassengerRecursively(Entity entity) {
|
||||
while (entity != null) {
|
||||
if (entity instanceof Player) {
|
||||
// Scrap the case of players riding players for the moment.
|
||||
return (Player) entity;
|
||||
}
|
||||
final Entity passenger = entity.getPassenger();
|
||||
if (entity.equals(passenger)) {
|
||||
// Just in case :9.
|
||||
break;
|
||||
}
|
||||
else {
|
||||
entity = passenger;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static int getStackCount(final InventoryView view, final ItemStack reference) {
|
||||
return getStackCount(view.getBottomInventory(), reference) + getStackCount(view.getTopInventory(), reference);
|
||||
}
|
||||
|
||||
/**
|
||||
// /**
|
||||
// * Search for players / passengers (broken by name: closes the inventory of
|
||||
// * first player found including entity and passengers recursively).
|
||||
// *
|
||||
// * @param entity
|
||||
// * the entity
|
||||
// * @return true, if successful
|
||||
// */
|
||||
// public static boolean closePlayerInventoryRecursively(Entity entity) {
|
||||
// // Find a player.
|
||||
// final Player player = PassengerUtil.getFirstPlayerIncludingPassengersRecursively(entity);
|
||||
// if (player != null && closeOpenInventory((Player) entity)) {
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Close one players inventory, if open. This might ignore
|
||||
* InventoryType.CRAFTING (see: hasInventoryOpen).
|
||||
*
|
||||
|
@ -146,16 +119,16 @@ public class InventoryUtil {
|
|||
* the player
|
||||
* @return If closed.
|
||||
*/
|
||||
public static boolean closeOpenInventory(final Player player) {
|
||||
if (hasInventoryOpen(player)) {
|
||||
player.closeInventory();
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
public static boolean closeOpenInventory(final Player player) {
|
||||
if (hasInventoryOpen(player)) {
|
||||
player.closeInventory();
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the players inventory is open. This might ignore
|
||||
* InventoryType.CRAFTING.
|
||||
*
|
||||
|
@ -163,10 +136,10 @@ public class InventoryUtil {
|
|||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public static boolean hasInventoryOpen(final Player player) {
|
||||
final InventoryView view = player.getOpenInventory();
|
||||
return view != null && view.getType() != InventoryType.CRAFTING;
|
||||
}
|
||||
public static boolean hasInventoryOpen(final Player player) {
|
||||
final InventoryView view = player.getOpenInventory();
|
||||
return view != null && view.getType() != InventoryType.CRAFTING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first consumable item found, checking main hand first and then
|
||||
|
|
|
@ -58,6 +58,7 @@ public class TeleportUtil {
|
|||
// TODO: Account for nested passengers and inconsistencies.
|
||||
final MovingData data = MovingData.getData(player);
|
||||
data.isVehicleSetBack = true;
|
||||
// TODO: Adjust to multiple passengers.
|
||||
final Entity passenger = vehicle.getPassenger();
|
||||
boolean vehicleTeleported = false;
|
||||
final boolean playerIsPassenger = player.equals(passenger);
|
||||
|
|
|
@ -84,4 +84,30 @@ public class PassengerUtil {
|
|||
return vehicle;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Get a player from an entity. This will return the first player found
|
||||
// * amongst the entity itself and passengers checked recursively.
|
||||
// *
|
||||
// * @param entity
|
||||
// * the entity
|
||||
// * @return the player passenger recursively
|
||||
// */
|
||||
// public static Player getFirstPlayerIncludingPassengersRecursively(Entity entity) {
|
||||
// while (entity != null) {
|
||||
// if (entity instanceof Player) {
|
||||
// // Scrap the case of players riding players for the moment.
|
||||
// return (Player) entity;
|
||||
// }
|
||||
// final Entity passenger = entity.getPassenger();
|
||||
// if (entity.equals(passenger)) {
|
||||
// // Just in case :9.
|
||||
// break;
|
||||
// }
|
||||
// else {
|
||||
// entity = passenger;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ package fr.neatmonster.nocheatplus.compat.registry;
|
|||
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.components.entity.IEntityAccessLastPositionAndLook;
|
||||
import fr.neatmonster.nocheatplus.components.entity.IEntityAccessVehicle;
|
||||
|
||||
/**
|
||||
* Set up more fine grained entity access providers, registered as generic
|
||||
|
@ -39,6 +40,8 @@ public class EntityAccessFactory {
|
|||
* @param config
|
||||
*/
|
||||
public void setupEntityAccess(final MCAccess mcAccess, final MCAccessConfig config) {
|
||||
|
||||
// IEntityAccessLastPositionAndLook
|
||||
RegistryHelper.setupGenericInstance(new String[] {
|
||||
"fr.neatmonster.nocheatplus.compat.cbdev.EntityAccessLastPositionAndLook",
|
||||
"fr.neatmonster.nocheatplus.compat.spigotcb1_10_R1.EntityAccessLastPositionAndLook",
|
||||
|
@ -47,6 +50,12 @@ public class EntityAccessFactory {
|
|||
}, new String[] {
|
||||
"fr.neatmonster.nocheatplus.compat.cbreflect.reflect.ReflectEntityLastPositionAndLook",
|
||||
}, IEntityAccessLastPositionAndLook.class, config, false);
|
||||
|
||||
// IEntityAccessVehicle
|
||||
RegistryHelper.registerFirstAvailable(new String[] {
|
||||
"fr.neatmonster.nocheatplus.compat.bukkit.EntityAccessVehicleMultiPassenger",
|
||||
"fr.neatmonster.nocheatplus.compat.bukkit.EntityAccessVehicleLegacy",
|
||||
}, IEntityAccessVehicle.class, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -162,4 +162,17 @@ public class RegistryHelper {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary method to register the first available class, using the default
|
||||
* constructor, logging registration state (and debug if desired).
|
||||
*
|
||||
* @param classNames
|
||||
* @param registerFor
|
||||
* @param logDebug
|
||||
* @return
|
||||
*/
|
||||
public static <T> T registerFirstAvailable(String[] classNames, Class<T> registerFor, boolean logDebug) {
|
||||
return registerGenericInstance(registerFor, getFirstAvailable(classNames, registerFor, logDebug));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue