From 26d7122a571852642ab02a7b4a8baa6d970c7885 Mon Sep 17 00:00:00 2001 From: asofold Date: Wed, 11 Mar 2015 22:55:00 +0100 Subject: [PATCH] Add dedicated compatibility module for MC 1.8 with CraftBukkit/Spigot. --- NCPCompatSpigotCB1_8/pom.xml | 31 +++ .../spigotcb1_8/BlockCacheSpigotCB1_8.java | 134 ++++++++++++ .../spigotcb1_8/MCAccessSpigotCB1_8.java | 193 ++++++++++++++++++ NCPPlugin/pom.xml | 5 + .../nocheatplus/compat/MCAccessFactory.java | 21 +- NoCheatPlus/pom.xml | 1 + pom.xml | 1 + 7 files changed, 380 insertions(+), 6 deletions(-) create mode 100644 NCPCompatSpigotCB1_8/pom.xml create mode 100644 NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/BlockCacheSpigotCB1_8.java create mode 100644 NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/MCAccessSpigotCB1_8.java diff --git a/NCPCompatSpigotCB1_8/pom.xml b/NCPCompatSpigotCB1_8/pom.xml new file mode 100644 index 00000000..3c9aa9cd --- /dev/null +++ b/NCPCompatSpigotCB1_8/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + fr.neatmonster + ncpcompatspigotcb1_8 + jar + NCPCompatSpigotCB1_8 + 1.1-SNAPSHOT + + + fr.neatmonster + nocheatplus-parent + 1.1-SNAPSHOT + + + + + fr.neatmonster + ncpcore + 1.1-SNAPSHOT + + + org.bukkit + craftbukkit + 1.8-R0.1-SNAPSHOT + + + + Compatibility for Minecraft 1.8 with CraftBukkit/Spigot. + + \ No newline at end of file diff --git a/NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/BlockCacheSpigotCB1_8.java b/NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/BlockCacheSpigotCB1_8.java new file mode 100644 index 00000000..f0cd4613 --- /dev/null +++ b/NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/BlockCacheSpigotCB1_8.java @@ -0,0 +1,134 @@ +package fr.neatmonster.nocheatplus.compat.spigotcb1_8; + +import java.util.Iterator; +import java.util.List; + +import net.minecraft.server.v1_8_R1.AxisAlignedBB; +import net.minecraft.server.v1_8_R1.BlockPosition; +import net.minecraft.server.v1_8_R1.EntityBoat; +import net.minecraft.server.v1_8_R1.EnumDirection; +import net.minecraft.server.v1_8_R1.IBlockAccess; +import net.minecraft.server.v1_8_R1.IBlockData; +import net.minecraft.server.v1_8_R1.TileEntity; + +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_8_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R1.entity.CraftEntity; +import org.bukkit.entity.Entity; + +import fr.neatmonster.nocheatplus.utilities.BlockCache; + +public class BlockCacheSpigotCB1_8 extends BlockCache implements IBlockAccess{ + + protected net.minecraft.server.v1_8_R1.WorldServer world; + protected World bukkitWorld; // WHACKS + + public BlockCacheSpigotCB1_8(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_8_R1.Block block = net.minecraft.server.v1_8_R1.Block.getById(id); + if (block == null) { + // TODO: Convention for null bounds -> full ? + return null; + } + block.updateShape(this, new BlockPosition(x, y, z)); + + // minX, minY, minZ, maxX, maxY, maxZ + return new double[]{block.z(), block.B(), block.D(), block.A(), block.C(), block.E()}; + } + + @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_8_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_8_R1.Entity other = (net.minecraft.server.v1_8_R1.Entity) iterator.next(); + if (!(other instanceof EntityBoat)){ // && !(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) { + return world.getType(pos); + } + + @Override + public boolean isEmpty(BlockPosition pos) { + return world.isEmpty(pos); + } + +} diff --git a/NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/MCAccessSpigotCB1_8.java b/NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/MCAccessSpigotCB1_8.java new file mode 100644 index 00000000..59310dcb --- /dev/null +++ b/NCPCompatSpigotCB1_8/src/main/java/fr/neatmonster/nocheatplus/compat/spigotcb1_8/MCAccessSpigotCB1_8.java @@ -0,0 +1,193 @@ +package fr.neatmonster.nocheatplus.compat.spigotcb1_8; + +import net.minecraft.server.v1_8_R1.AxisAlignedBB; +import net.minecraft.server.v1_8_R1.Block; +import net.minecraft.server.v1_8_R1.DamageSource; +import net.minecraft.server.v1_8_R1.EntityComplexPart; +import net.minecraft.server.v1_8_R1.EntityPlayer; +import net.minecraft.server.v1_8_R1.MobEffectList; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.command.CommandMap; +import org.bukkit.craftbukkit.v1_8_R1.CraftServer; +import org.bukkit.craftbukkit.v1_8_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_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.BlockCache; +import fr.neatmonster.nocheatplus.utilities.ReflectionUtil; + +public class MCAccessSpigotCB1_8 implements MCAccess{ + + /** + * Constructor to let it fail. + */ + public MCAccessSpigotCB1_8() { + getCommandMap(); + ReflectionUtil.checkMembers("net.minecraft.server.v1_8_R1.", new String[] {"Entity" , "dead"}); + // block bounds, original: minX, maxX, minY, maxY, minZ, maxZ + ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_8_R1.Block.class, + new String[]{"z", "A", "B", "C", "D", "E"}, double.class); + // TODO: Nail it down further. + } + + @Override + public String getMCVersion() { + // 1_8_R1 + return "1.8"; + } + + @Override + public String getServerVersionTag() { + return "Spigot-CB-DEV"; + } + + @Override + public CommandMap getCommandMap() { + return ((CraftServer) Bukkit.getServer()).getCommandMap(); + } + + @Override + public BlockCache getBlockCache(final World world) { + return new BlockCacheSpigotCB1_8(world); + } + + @Override + public double getHeight(final Entity entity) { + final net.minecraft.server.v1_8_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; + } + + @Override + public AlmostBoolean isBlockSolid(final int id) { + final Block block = Block.getById(id); + if (block == null || block.getMaterial() == null) { + return AlmostBoolean.MAYBE; + } + else { + return AlmostBoolean.match(block.getMaterial().isSolid()); + } + } + + @Override + public AlmostBoolean isBlockLiquid(final int id) { + final Block block = Block.getById(id); + if (block == null || block.getMaterial() == null) { + return AlmostBoolean.MAYBE; + } + else { + return AlmostBoolean.match(block.getMaterial().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(MobEffectList.JUMP)) { + return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier(); + } + else { + return Double.NEGATIVE_INFINITY; + } + } + + @Override + public double getFasterMovementAmplifier(final Player player) { + final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle(); + if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) { + return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier(); + } + else { + return Double.NEGATIVE_INFINITY; + } + } + + @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 738b86d1..eb2830e0 100644 --- a/NCPPlugin/pom.xml +++ b/NCPPlugin/pom.xml @@ -90,6 +90,11 @@ ncpcompatcb3100 1.1-SNAPSHOT + + fr.neatmonster + ncpcompatspigotcb1_8 + 1.1-SNAPSHOT + fr.neatmonster ncpcompatcbdev 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 110855ec..fff180cb 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/MCAccessFactory.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/MCAccessFactory.java @@ -20,6 +20,7 @@ import fr.neatmonster.nocheatplus.compat.cb3026.MCAccessCB3026; import fr.neatmonster.nocheatplus.compat.cb3043.MCAccessCB3043; import fr.neatmonster.nocheatplus.compat.cb3100.MCAccessCB3100; import fr.neatmonster.nocheatplus.compat.glowstone.MCAccessGlowstone; +import fr.neatmonster.nocheatplus.compat.spigotcb1_8.MCAccessSpigotCB1_8; import fr.neatmonster.nocheatplus.logging.StaticLog; /** @@ -97,20 +98,28 @@ public class MCAccessFactory { * @return Valid MCAccess instance or null. */ private MCAccess getMCAccessCraftBukkit(List throwables) { - + // TODO: Quick return check (note special forks and package info not being usable). // TEMP // // Only add as long as no stable module has been added. - // 1.8 (Spigot) + // TODO: 1.8.3 (Spigot) +// try{ +// return new fr.neatmonster.nocheatplus.compat.cbdev.MCAccessCBDev(); +// } +// catch(Throwable t) { +// throwables.add(t); +// }; + // TEMP END // + + // 1.8 try{ - return new fr.neatmonster.nocheatplus.compat.cbdev.MCAccessCBDev(); + return new MCAccessSpigotCB1_8(); } catch(Throwable t) { throwables.add(t); }; - // TEMP END // - + // 1.7.10 try{ return new MCAccessCB3100(); @@ -118,7 +127,7 @@ public class MCAccessFactory { catch(Throwable t) { throwables.add(t); }; - + // 1.7.8|1.7.9 try{ return new MCAccessCB3043(); diff --git a/NoCheatPlus/pom.xml b/NoCheatPlus/pom.xml index 3c72e63e..ffd65dad 100644 --- a/NoCheatPlus/pom.xml +++ b/NoCheatPlus/pom.xml @@ -93,6 +93,7 @@ fr.neatmonster:ncpcompatcb3026 fr.neatmonster:ncpcompatcb3043 fr.neatmonster:ncpcompatcb3100 + fr.neatmonster:ncpcompatspigotcb1_8 fr.neatmonster:ncpcompatcbdev fr.neatmonster:ncpcompatprotocollib fr.neatmonster:ncpcompatglowstone diff --git a/pom.xml b/pom.xml index 651f1e83..64eaf7b1 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ NCPCompatCB3026 NCPCompatCB3043 NCPCompatCB3100 + NCPCompatSpigotCB1_8 NCPCompatCBDev NCPCompatProtocolLib NCPCompatGlowstone