From 0280db501007310f6141801560e8dbc58529f438 Mon Sep 17 00:00:00 2001 From: asofold Date: Wed, 11 May 2016 00:27:21 +0200 Subject: [PATCH] Dedicated compat module for Spigot/CraftBukkit 1.9-1.9.3 (1.9_R1). --- .../compat/bukkit/MCAccessBukkitBase.java | 2 +- NCPCompatSpigotCB1_9_R1/pom.xml | 45 +++ .../BlockCacheSpigotCB1_9_R1.java | 141 +++++++++ .../MCAccessSpigotCB1_9_R1.java | 274 ++++++++++++++++++ NCPPlugin/pom.xml | 9 +- .../nocheatplus/compat/MCAccessFactory.java | 3 +- pom.xml | 5 +- 7 files changed, 473 insertions(+), 6 deletions(-) create mode 100644 NCPCompatSpigotCB1_9_R1/pom.xml create mode 100644 NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/BlockCacheSpigotCB1_9_R1.java create mode 100644 NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/MCAccessSpigotCB1_9_R1.java diff --git a/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkitBase.java b/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkitBase.java index 729f77aa6..2080d148e 100644 --- a/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkitBase.java +++ b/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkitBase.java @@ -40,7 +40,7 @@ public MCAccessBukkitBase() { public String getMCVersion() { // Bukkit API. // TODO: maybe output something else. - return "1.4.6|1.4.7|1.5.x|1.6.x|1.7.x|1.8.x|?"; // 1.8.x is bold! + return "1.4.6|1.4.7|1.5.x|1.6.x|1.7.x|1.8.x|1.9.x|?"; // 1.8.x is bold! } @Override diff --git a/NCPCompatSpigotCB1_9_R1/pom.xml b/NCPCompatSpigotCB1_9_R1/pom.xml new file mode 100644 index 000000000..5abbfe00c --- /dev/null +++ b/NCPCompatSpigotCB1_9_R1/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + fr.neatmonster + ncpcompatspigotcb1_9_r1 + jar + NCPCompatSpigotCB1_9_R1 + 1.1-SNAPSHOT + + + fr.neatmonster + nocheatplus-parent + 1.1-SNAPSHOT + + + + + fr.neatmonster + ncpcore + 1.1-SNAPSHOT + provided + + + org.bukkit + craftbukkit + 1.9-R0.1-SNAPSHOT + provided + + + + Compatibility for Minecraft 1.9-1.9.3 with CraftBukkit/Spigot (1_9_R1). + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + \ No newline at end of file diff --git a/NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/BlockCacheSpigotCB1_9_R1.java b/NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/BlockCacheSpigotCB1_9_R1.java new file mode 100644 index 000000000..ae7a64623 --- /dev/null +++ b/NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/BlockCacheSpigotCB1_9_R1.java @@ -0,0 +1,141 @@ +package fr.neatmonster.nocheatplus.compat.spigotcb1_9_R1; + +import java.util.Iterator; +import java.util.List; + +import net.minecraft.server.v1_9_R1.AxisAlignedBB; +import net.minecraft.server.v1_9_R1.BlockPosition; +import net.minecraft.server.v1_9_R1.EntityBoat; +import net.minecraft.server.v1_9_R1.EntityShulker; +import net.minecraft.server.v1_9_R1.EnumDirection; +import net.minecraft.server.v1_9_R1.IBlockAccess; +import net.minecraft.server.v1_9_R1.IBlockData; +import net.minecraft.server.v1_9_R1.TileEntity; + +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_9_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; +import org.bukkit.entity.Entity; + +import fr.neatmonster.nocheatplus.utilities.BlockCache; + +public class BlockCacheSpigotCB1_9_R1 extends BlockCache implements IBlockAccess { + + protected net.minecraft.server.v1_9_R1.WorldServer world; + protected World bukkitWorld; + + public BlockCacheSpigotCB1_9_R1(World world) { + setAccess(world); + } + + @Override + public void setAccess(World world) { + if (world != null) { + this.maxBlockY = world.getMaxHeight() - 1; + this.world = ((CraftWorld) world).getHandle(); + this.bukkitWorld = world; + } else { + this.world = null; + this.bukkitWorld = null; + } + } + + @SuppressWarnings("deprecation") + @Override + public int fetchTypeId(final int x, final int y, final int z) { + return bukkitWorld.getBlockTypeIdAt(x, y, z); + } + + @SuppressWarnings("deprecation") + @Override + public int fetchData(final int x, final int y, final int z) { + return bukkitWorld.getBlockAt(x, y, z).getData(); + } + + @Override + public double[] fetchBounds(final int x, final int y, final int z){ + final int id = getTypeId(x, y, z); + final net.minecraft.server.v1_9_R1.Block block = net.minecraft.server.v1_9_R1.Block.getById(id); + if (block == null) { + // TODO: Convention for null blocks -> full ? + return null; + } + final BlockPosition pos = new BlockPosition(x, y, z); + final AxisAlignedBB bb = block.a(getType(pos), this, pos); + if (bb == null) { + return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0}; // Special case. + //return null; + } + // minX, minY, minZ, maxX, maxY, maxZ + return new double[]{bb.a, bb.b, bb.c, bb.d, bb.e, bb.f}; + } + + @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){ + try{ + // TODO: Find some simplification! + + final net.minecraft.server.v1_9_R1.Entity mcEntity = ((CraftEntity) entity).getHandle(); + + final AxisAlignedBB box = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + @SuppressWarnings("rawtypes") + final List list = world.getEntities(mcEntity, box); + @SuppressWarnings("rawtypes") + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + final net.minecraft.server.v1_9_R1.Entity other = (net.minecraft.server.v1_9_R1.Entity) iterator.next(); + if (mcEntity == other || !(other instanceof EntityBoat) && !(other instanceof EntityShulker)) { // && !(other instanceof EntityMinecart)) continue; + continue; + } + if (minY >= other.locY && minY - other.locY <= 0.7){ + return true; + } + // Still check this for some reason. + final AxisAlignedBB otherBox = other.getBoundingBox(); + if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) { + continue; + } + else { + return true; + } + } + } + catch (Throwable t){ + // Ignore exceptions (Context: DisguiseCraft). + } + return false; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.utilities.BlockCache#cleanup() + */ + @Override + public void cleanup() { + super.cleanup(); + world = null; + bukkitWorld = null; + } + + @Override + public int getBlockPower(BlockPosition pos, EnumDirection dir) { + return world.getBlockPower(pos, dir); + } + + @Override + public TileEntity getTileEntity(BlockPosition pos) { + return world.getTileEntity(pos); + } + + @Override + public IBlockData getType(BlockPosition pos) { + // TODO: Can this be cached ? + return world.getType(pos); + } + + @Override + public boolean isEmpty(BlockPosition pos) { + // TODO: Can (and should) this be cached ? + return world.isEmpty(pos); + } + +} diff --git a/NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/MCAccessSpigotCB1_9_R1.java b/NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/MCAccessSpigotCB1_9_R1.java new file mode 100644 index 000000000..ac8fa62a6 --- /dev/null +++ b/NCPCompatSpigotCB1_9_R1/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_9_R1/MCAccessSpigotCB1_9_R1.java @@ -0,0 +1,274 @@ +package fr.neatmonster.nocheatplus.compat.spigotcb1_9_R1; + +import net.minecraft.server.v1_9_R1.AttributeInstance; +import net.minecraft.server.v1_9_R1.AttributeModifier; +import net.minecraft.server.v1_9_R1.AxisAlignedBB; +import net.minecraft.server.v1_9_R1.Block; +import net.minecraft.server.v1_9_R1.BlockPosition; +import net.minecraft.server.v1_9_R1.DamageSource; +import net.minecraft.server.v1_9_R1.EntityComplexPart; +import net.minecraft.server.v1_9_R1.EntityPlayer; +import net.minecraft.server.v1_9_R1.GenericAttributes; +import net.minecraft.server.v1_9_R1.IBlockAccess; +import net.minecraft.server.v1_9_R1.IBlockData; +import net.minecraft.server.v1_9_R1.MobEffectList; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.command.CommandMap; +import org.bukkit.craftbukkit.v1_9_R1.CraftServer; +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftLivingEntity; +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.compat.AlmostBoolean; +import fr.neatmonster.nocheatplus.compat.MCAccess; +import fr.neatmonster.nocheatplus.utilities.AttribUtil; +import fr.neatmonster.nocheatplus.utilities.BlockCache; +import fr.neatmonster.nocheatplus.utilities.ReflectionUtil; + +public class MCAccessSpigotCB1_9_R1 implements MCAccess { + + private final MobEffectList JUMP; + private final MobEffectList FASTER_MOVEMENT; + + /** + * Test for availability in constructor. + */ + public MCAccessSpigotCB1_9_R1() { + // try { + getCommandMap(); + if (ReflectionUtil.getMethod(Block.class, "a", IBlockData.class, IBlockAccess.class, BlockPosition.class).getReturnType() != AxisAlignedBB.class) { + throw new RuntimeException(); + } + if (ReflectionUtil.getConstructor(BlockPosition.class, int.class, int.class, int.class) == null) { + throw new RuntimeException(); + } + ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_9_R1.EntityLiving.class, + new String[]{"getHeadHeight"}, float.class); + ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_9_R1.EntityPlayer.class, + new String[]{"getHealth"}, float.class); + ReflectionUtil.checkMembers(net.minecraft.server.v1_9_R1.AxisAlignedBB.class, double.class, + "a", "b", "c", "d", "e", "f"); + ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_9_R1.AttributeInstance.class, + new String[]{"b"}, double.class); + ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_9_R1.AttributeModifier.class, + new String[]{"c"}, int.class); + ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_9_R1.AttributeModifier.class, + new String[]{"d"}, double.class); + ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_9_R1.Material.class, + new String[]{"isSolid", "isLiquid"}, boolean.class); + // TODO: Confine the following by types as well. + ReflectionUtil.checkMembers("net.minecraft.server.v1_9_R1.", + new String[] {"Entity" , "length", "width", "locY"}); + ReflectionUtil.checkMembers("net.minecraft.server.v1_9_R1.", + new String[] {"EntityPlayer" , "dead", "deathTicks", "invulnerableTicks"}); + + // obc: getHandle() for CraftWorld, CraftPlayer, CraftEntity. + // nms: Several: AxisAlignedBB, WorldServer + // nms: Block.getById(int), BlockPosition(int, int, int), WorldServer.getEntities(Entity, AxisAlignedBB) + // nms: AttributeInstance.a(UUID), EntityComplexPart, EntityPlayer.getAttributeInstance(IAttribute). + + // } catch(Throwable t) { + // NCPAPIProvider.getNoCheatPlusAPI().getLogManager().severe(Streams.INIT, t); + // throw new RuntimeException("NO WERK"); + // } + JUMP = MobEffectList.getByName("jump_boost"); + if (JUMP == null) { + throw new RuntimeException(); + } + FASTER_MOVEMENT = MobEffectList.getByName("speed"); + if (FASTER_MOVEMENT == null) { + throw new RuntimeException(); + } + } + + @Override + public String getMCVersion() { + // 1.9-1.9.3 (1_9_R1) + return "1.9-1.9.3"; + } + + @Override + public String getServerVersionTag() { + return "Spigot-CB-1.9_R1"; + } + + @Override + public CommandMap getCommandMap() { + return ((CraftServer) Bukkit.getServer()).getCommandMap(); + } + + @Override + public BlockCache getBlockCache(final World world) { + return new BlockCacheSpigotCB1_9_R1(world); + } + + @Override + public double getHeight(final Entity entity) { + final net.minecraft.server.v1_9_R1.Entity mcEntity = ((CraftEntity) entity).getHandle(); + AxisAlignedBB boundingBox = mcEntity.getBoundingBox(); + final double entityHeight = Math.max(mcEntity.length, Math.max(mcEntity.getHeadHeight(), boundingBox.e - boundingBox.b)); + if (entity instanceof LivingEntity) { + return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight); + } else return entityHeight; + } + + private net.minecraft.server.v1_9_R1.Material getMaterial(int blockId) { + final Block block = Block.getById(blockId); + if (block == null) { + return null; + } + // (Currently no update state, since we don't have any position.) + return block.q(block.getBlockData()); + } + + @Override + public AlmostBoolean isBlockSolid(final int id) { + final net.minecraft.server.v1_9_R1.Material material = getMaterial(id); + if (material == null) { + return AlmostBoolean.MAYBE; + } + else { + return AlmostBoolean.match(material.isSolid()); + } + } + + @Override + public AlmostBoolean isBlockLiquid(final int id) { + final net.minecraft.server.v1_9_R1.Material material = getMaterial(id); + if (material == null) { + return AlmostBoolean.MAYBE; + } + else { + return AlmostBoolean.match(material.isLiquid()); + } + } + + @Override + public double getWidth(final Entity entity) { + return ((CraftEntity) entity).getHandle().width; + } + + @Override + public AlmostBoolean isIllegalBounds(final Player player) { + final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + if (entityPlayer.dead) { + return AlmostBoolean.NO; + } + // TODO: Does this need a method call for the "real" box? Might be no problem during moving events, though. + final AxisAlignedBB box = entityPlayer.getBoundingBox(); + if (!entityPlayer.isSleeping()) { + // This can not really test stance but height of bounding box. + final double dY = Math.abs(box.e - box.b); + if (dY > 1.8) { + return AlmostBoolean.YES; // dY > 1.65D || + } + if (dY < 0.1D && entityPlayer.length >= 0.1) { + return AlmostBoolean.YES; + } + } + return AlmostBoolean.MAYBE; + } + + @Override + public double getJumpAmplifier(final Player player) { + final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle(); + if (mcPlayer.hasEffect(JUMP)) { + return mcPlayer.getEffect(JUMP).getAmplifier(); + } + else { + return Double.NEGATIVE_INFINITY; + } + } + + @Override + public double getFasterMovementAmplifier(final Player player) { + final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle(); + if (mcPlayer.hasEffect(FASTER_MOVEMENT)) { + return mcPlayer.getEffect(FASTER_MOVEMENT).getAmplifier(); + } + else { + return Double.NEGATIVE_INFINITY; + } + } + + @Override + public double getSpeedAttributeMultiplier(Player player) { + final AttributeInstance attr = ((CraftLivingEntity) player).getHandle().getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); + final double val = attr.getValue() / attr.b(); + final AttributeModifier mod = attr.a(AttribUtil.ID_SPRINT_BOOST); + if (mod == null) { + return val; + } else { + return val / AttribUtil.getMultiplier(mod.c(), mod.d()); + } + } + + @Override + public double getSprintAttributeMultiplier(Player player) { + final AttributeModifier mod = ((CraftLivingEntity) player).getHandle().getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).a(AttribUtil.ID_SPRINT_BOOST); + if (mod == null) { + return 1.0; + } else { + return AttribUtil.getMultiplier(mod.c(), mod.d()); + } + } + + @Override + public int getInvulnerableTicks(final Player player) { + return ((CraftPlayer) player).getHandle().invulnerableTicks; + } + + @Override + public void setInvulnerableTicks(final Player player, final int ticks) { + ((CraftPlayer) player).getHandle().invulnerableTicks = ticks; + } + + @Override + public void dealFallDamage(final Player player, final double damage) { + ((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, (float) damage); + } + + @Override + public boolean isComplexPart(final Entity entity) { + return ((CraftEntity) entity).getHandle() instanceof EntityComplexPart; + } + + @Override + public boolean shouldBeZombie(final Player player) { + final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle(); + return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ; + } + + @Override + public void setDead(final Player player, final int deathTicks) { + final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle(); + mcPlayer.deathTicks = deathTicks; + mcPlayer.dead = true; + } + + @Override + public boolean hasGravity(final Material mat) { + return mat.hasGravity(); + } + + @Override + public AlmostBoolean dealFallDamageFiresAnEvent() { + return AlmostBoolean.YES; + } + + // @Override + // public void correctDirection(final Player player) { + // final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle(); + // // Main direction. + // mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw); + // mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch); + // // Consider setting the lastYaw here too. + // } + +} diff --git a/NCPPlugin/pom.xml b/NCPPlugin/pom.xml index dcfc2f0f1..7c5e202c8 100644 --- a/NCPPlugin/pom.xml +++ b/NCPPlugin/pom.xml @@ -123,6 +123,11 @@ ncpcompatspigotcb1_8_r3 1.1-SNAPSHOT + + fr.neatmonster + ncpcompatspigotcb1_9_r1 + 1.1-SNAPSHOT + fr.neatmonster ncpcompatcbdev @@ -225,7 +230,7 @@ fr.neatmonster - ncpcompatcbdev + ncpcompatspigotcb1_9_r1 1.1-SNAPSHOT @@ -275,7 +280,7 @@ fr.neatmonster - ncpcompatcbdev + ncpcompatspigotcb1_9_r1 1.1-SNAPSHOT diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/MCAccessFactory.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/MCAccessFactory.java index 3ac7f4e56..901453f3f 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/MCAccessFactory.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/MCAccessFactory.java @@ -105,9 +105,10 @@ private MCAccess getMCAccessCraftBukkit(List throwables) { final String[] classNames = new String[] { // Current DEV / LATEST: CB (Spigot) - "fr.neatmonster.nocheatplus.compat.cbdev.MCAccessCBDev", // future / tests. + //"fr.neatmonster.nocheatplus.compat.cbdev.MCAccessCBDev", // future / tests. //"fr.neatmonster.nocheatplus.compat.cbreflect.MCAccessCBReflect", // TEST // Dedicated: CB (Spigot) + "fr.neatmonster.nocheatplus.compat.spigotcb1_9_R1.MCAccessSpigotCB1_9_R1", // 1.9.1.9.3 (1_9_R1) "fr.neatmonster.nocheatplus.compat.spigotcb1_8_R3.MCAccessSpigotCB1_8_R3", // 1.8.4-1.8.8 (1_8_R3) "fr.neatmonster.nocheatplus.compat.spigotcb1_8_R2.MCAccessSpigotCB1_8_R2", // 1.8.3 (1_8_R2) "fr.neatmonster.nocheatplus.compat.spigotcb1_8_R1.MCAccessSpigotCB1_8_R1", // 1.8 (1_8_R1) diff --git a/pom.xml b/pom.xml index 3e833c0dd..3666bb04a 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,7 @@ NCPCompatSpigotCB1_8_R1 NCPCompatSpigotCB1_8_R2 NCPCompatSpigotCB1_8_R3 + NCPCompatSpigotCB1_9_R1 NCPCompatCBDev NCPCompatProtocolLib @@ -92,7 +93,7 @@ NCPCore NCPCompatBukkit - NCPCompatCBDev + NCPCompatSpigotCB1_9_R1 NCPCompatProtocolLib NCPCompatGlowstone @@ -114,7 +115,7 @@ NCPCore NCPCompatBukkit - NCPCompatCBDev + NCPCompatSpigotCB1_9_R1 NCPCompatProtocolLib NCPCompatGlowstone