[SAFETY COMMIT, INCOMPLETE] RAW: Add support for bukkit-api-only.

This commit is contained in:
asofold 2013-01-20 00:51:09 +01:00
parent c8c4d4c9cc
commit 8e313f4a47
6 changed files with 324 additions and 29 deletions

View File

@ -0,0 +1,64 @@
package fr.neatmonster.nocheatplus.compat.bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
public class BlockCacheBukkit extends BlockCache{
protected World world;
public BlockCacheBukkit(World world) {
setAccess(world);
}
@Override
public void setAccess(World world) {
this.world = world;
}
@Override
public int fetchTypeId(final int x, final int y, final int z) {
// TODO: consider setting type id and data at once.
return world.getBlockTypeIdAt(x, y, z);
}
@Override
public int fetchData(final int x, final int y, final int z) {
// TODO: consider setting type id and data at once.
return world.getBlockAt(x, y, z).getData();
}
@Override
public double[] fetchBounds(final int x, final int y, final int z){
// 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[]{0f, 0f, 0f, 1f, 1f, 1f};
}
@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: Probably check other ids too before doing this ?
for (final Entity other : entity.getNearbyEntities(2.0, 2.0, 2.0)){
final EntityType type = other.getType();
if (type != EntityType.BOAT && type != EntityType.MINECART) continue;
final Location loc = entity.getLocation();
if (Math.abs(loc.getY() - minY) < 0.6){
// 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).
}
return false;
}
}

View File

@ -0,0 +1,169 @@
package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.Collection;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.command.CommandMap;
import org.bukkit.entity.ComplexEntityPart;
import org.bukkit.entity.ComplexLivingEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
public class MCAccessBukkit implements MCAccess{
/**
* Get amplifier for a potion effect.
* @param player
* @param type
* @return
*/
public static double getPotionEffectAmplifier(final Player player, final PotionEffectType type) {
if (!player.hasPotionEffect(type)) return Double.MIN_VALUE;
final Collection<PotionEffect> effects = player.getActivePotionEffects();
double max = Double.MIN_VALUE;
for (final PotionEffect effect : effects){
if (effect.getType() == type){
max = Math.max(max, effect.getAmplifier());
}
}
return max;
}
/**
* Constructor to let it fail.
*/
public MCAccessBukkit(){
// TODO: ...
}
@Override
public String getMCVersion() {
// Bukkit API.
// TODO: maybe output something else.
return "?";
}
@Override
public String getServerVersionTag() {
return "Bukkit-API";
}
@Override
public CommandMap getCommandMap() {
return null;
}
@Override
public BlockCache getBlockCache(final World world) {
return new BlockCacheBukkit(world);
}
@Override
public double getHeight(final Entity entity) {
final double entityHeight = 1.0;
if (entity instanceof LivingEntity) {
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
} else return entityHeight;
}
@Override
public AlmostBoolean isBlockSolid(final int id) {
final Material mat = Material.getMaterial(id);
if (mat == null) return AlmostBoolean.MAYBE;
else return AlmostBoolean.match(mat.isSolid());
}
@Override
public AlmostBoolean isBlockLiquid(final int id) {
final Material mat = Material.getMaterial(id);
if (mat == null) return AlmostBoolean.MAYBE;
switch (mat) {
case STATIONARY_LAVA:
case STATIONARY_WATER:
case WATER:
case LAVA:
return AlmostBoolean.YES;
}
return AlmostBoolean.NO;
}
@Override
public boolean Block_i(final int id) {
// TODO: This is inaccurate (would be something like "can suffocate"), however it is used for piling upwards and might about do.
return BlockProperties.isGround(id) || BlockProperties.isSolid(id);
}
@Override
public double getWidth(final Entity entity) {
// TODO
return 0.6;
}
@Override
public AlmostBoolean isIllegalBounds(final Player player) {
if (player.isDead()) return AlmostBoolean.NO;
if (!player.isSleeping()){ // TODO: ignored sleeping ?
// TODO: This can test like ... nothing !
// (Might not be necessary.)
}
return AlmostBoolean.MAYBE;
}
@Override
public double getJumpAmplifier(final Player player) {
return getPotionEffectAmplifier(player, PotionEffectType.JUMP);
}
@Override
public double getFasterMovementAmplifier(final Player player) {
return getPotionEffectAmplifier(player, PotionEffectType.SPEED);
}
@Override
public int getInvulnerableTicks(final Player player) {
// TODO: Ahhh...
return player.getNoDamageTicks();
}
@Override
public void setInvulnerableTicks(final Player player, final int ticks) {
// TODO: Ahhh...
player.setLastDamageCause(new EntityDamageEvent(player, DamageCause.CUSTOM, 500));
player.setNoDamageTicks(ticks);
}
@Override
public void dealFallDamage(final Player player, final int damage) {
// TODO: account for armor, other.
player.damage(damage);
}
@Override
public boolean isComplexPart(final Entity entity) {
return entity instanceof ComplexEntityPart || entity instanceof ComplexLivingEntity;
}
@Override
public boolean shouldBeZombie(final Player player) {
return player.getHealth() <= 0 || player.isDead();
}
@Override
public void setDead(final Player player, final int deathTicks) {
// TODO: Test / kick ? ...
player.setHealth(0);
player.damage(1);
}
}

View File

@ -3,11 +3,16 @@ package fr.neatmonster.nocheatplus.command;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandMap; import org.bukkit.command.CommandMap;
import org.bukkit.command.SimpleCommandMap; import org.bukkit.command.SimpleCommandMap;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import fr.neatmonster.nocheatplus.NoCheatPlus; import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
@ -40,8 +45,21 @@ public class CommandUtil {
return ((SimpleCommandMap) commandMap).getCommands(); return ((SimpleCommandMap) commandMap).getCommands();
} }
else{ else{
// TODO: Find a way to also secure server commands. final Collection<Command> commands = new LinkedHashSet<Command>(100);
throw new RuntimeException("Can not handle other than SimpleCommandMap."); for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()){
if (plugin instanceof JavaPlugin){
final JavaPlugin javaPlugin = (JavaPlugin) plugin;
final Map<String, Map<String, Object>> map = javaPlugin.getDescription().getCommands();
if (map != null){
for (String label : map.keySet()){
Command command = javaPlugin.getCommand(label);
if (command != null) commands.add(command);
}
}
}
}
// TODO: Vanilla / CB commands !?
return commands;
} }
} }
@ -65,9 +83,14 @@ public class CommandUtil {
* @return * @return
*/ */
public static Command getCommand(final String alias) { public static Command getCommand(final String alias) {
final CommandMap map = getCommandMap();
final String lcAlias = alias.trim().toLowerCase(); final String lcAlias = alias.trim().toLowerCase();
return map.getCommand(lcAlias); final CommandMap map = getCommandMap();
if (map != null){
return map.getCommand(lcAlias);
} else {
// TODO: maybe match versus plugin commands.
return null;
}
} }
/** /**

View File

@ -3,10 +3,13 @@ package fr.neatmonster.nocheatplus.compat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import fr.neatmonster.nocheatplus.compat.bukkit.MCAccessBukkit;
import fr.neatmonster.nocheatplus.compat.cb2511.MCAccessCB2511; import fr.neatmonster.nocheatplus.compat.cb2511.MCAccessCB2511;
import fr.neatmonster.nocheatplus.compat.cb2512.MCAccessCB2512; import fr.neatmonster.nocheatplus.compat.cb2512.MCAccessCB2512;
import fr.neatmonster.nocheatplus.compat.cb2545.MCAccessCB2545; import fr.neatmonster.nocheatplus.compat.cb2545.MCAccessCB2545;
import fr.neatmonster.nocheatplus.compat.cbdev.MCAccessCBDev; import fr.neatmonster.nocheatplus.compat.cbdev.MCAccessCBDev;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.utilities.LogUtil; import fr.neatmonster.nocheatplus.utilities.LogUtil;
/** /**
@ -16,45 +19,79 @@ import fr.neatmonster.nocheatplus.utilities.LogUtil;
*/ */
public class MCAccessFactory { public class MCAccessFactory {
private final String[] updateLocs = new String[]{
"[NoCheatPlus] Check for updates at BukkitDev: http://dev.bukkit.org/server-mods/nocheatplus/",
"[NoCheatPlus] Development builds: http://nocheatplus.org:8080/job/NoCheatPlus/",
};
/** /**
* @throws RuntimeException if no access can be set. * @throws RuntimeException if no access can be set.
* @return * @return
*/ */
public MCAccess getMCAccess(){ public MCAccess getMCAccess(){
final List<Throwable> throwables = new ArrayList<Throwable>(); final List<Throwable> throwables = new ArrayList<Throwable>();
final boolean bukkitOnly = ConfigManager.getConfigFile().getBoolean(ConfPaths.COMPATIBILITY_BUKKITONLY);
// TEST // // Try to set up native access.
try{ if (!bukkitOnly){
return new MCAccessCBDev(); // TEST //
try{
return new MCAccessCBDev();
}
catch(Throwable t){
throwables.add(t);
};
// TEST END //
// TODO: add 1.4.7 classes explicitly.
try{
return new MCAccessCB2545();
}
catch(Throwable t){
throwables.add(t);
};
try{
return new MCAccessCB2512();
}
catch(Throwable t){
throwables.add(t);
};
try{
return new MCAccessCB2511();
}
catch(Throwable t){
throwables.add(t);
};
} }
catch(Throwable t){
throwables.add(t);
};
// TEST END //
// Try to set up api-only access.
try{ try{
return new MCAccessCB2545(); final String msg;
if (bukkitOnly){
msg = "[NoCheatPlus] The plugin is configured for Bukkit-API-only access is configured.";
}
else{
msg = "[NoCheatPlus] Could not set up non-api access for your specific Minecraft or server-mod version.";
}
LogUtil.logSevere("[NoCheatPlus] Some features will likely not function properly, performance might suffer.");
LogUtil.logWarning(msg);
for (String uMsg : updateLocs){
LogUtil.logWarning(uMsg);
}
return new MCAccessBukkit();
} }
catch(Throwable t){ catch(Throwable t){
throwables.add(t); throwables.add(t);
}; };
try{ // All went wrong.
return new MCAccessCB2512(); LogUtil.logSevere("[NoCheatPlus] Your version of NoCheatPlus does not seem to provide support for either your Minecraft version or your specific server-mod.");
for (String msg : updateLocs){
LogUtil.logSevere(msg);
} }
catch(Throwable t){
throwables.add(t);
};
try{
return new MCAccessCB2511();
}
catch(Throwable t){
throwables.add(t);
};
LogUtil.logSevere("[NoCheatPlus] Your version of NoCheatPlus does not seem to be compatible with either your Minecraft version or your specific serve-mod.");
LogUtil.logSevere("[NoCheatPlus] Check for updates at BukkitDev: http://dev.bukkit.org/server-mods/nocheatplus/");
LogUtil.logSevere("[NoCheatPlus] Development builds: http://nocheatplus.org:8080/job/NoCheatPlus/");
LogUtil.logSevere("[NoCheatPlus] Could not set up MC version specific access."); LogUtil.logSevere("[NoCheatPlus] Could not set up MC version specific access.");
for (Throwable t : throwables ){ for (Throwable t : throwables ){
LogUtil.logSevere(t); LogUtil.logSevere(t);

View File

@ -522,7 +522,8 @@ public abstract class ConfPaths {
// Compatibility section (possibly temporary). // Compatibility section (possibly temporary).
@GlobalConfig @GlobalConfig
public static final String COMPATIBILITY = "compatibility."; public static final String COMPATIBILITY = "compatibility.";
public static final String COMPATIBILITY_BLOCKS = COMPATIBILITY + "blocks."; public static final String COMPATIBILITY_BUKKITONLY = COMPATIBILITY + "bukkitapionly";
public static final String COMPATIBILITY_BLOCKS = COMPATIBILITY + "blocks.";
// Sub paths that are used with different path prefixes potentially. // Sub paths that are used with different path prefixes potentially.
public static final String SUB_DEBUG = "debug"; public static final String SUB_DEBUG = "debug";

View File

@ -25,7 +25,7 @@ public class DefaultConfig extends ConfigFile {
* NCP build needed for this config. * NCP build needed for this config.
* (Should only increment with changing or removing paths.) * (Should only increment with changing or removing paths.)
*/ */
public static final int buildNumber = 315; // TODO: Check jenkins... public static final int buildNumber = 322;
// TODO: auto input full version or null to an extra variable or several [fail safe for other syntax checking]? // TODO: auto input full version or null to an extra variable or several [fail safe for other syntax checking]?
@ -465,6 +465,7 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.STRINGS + ".tempkick1", "ncp tempkick [player] 1 Wait a minute!"); set(ConfPaths.STRINGS + ".tempkick1", "ncp tempkick [player] 1 Wait a minute!");
set(ConfPaths.STRINGS + ".tempkick5", "ncp tempkick [player] 5 You have five minutes to think about it!"); set(ConfPaths.STRINGS + ".tempkick5", "ncp tempkick [player] 5 You have five minutes to think about it!");
set(ConfPaths.COMPATIBILITY_BUKKITONLY, false);
set(ConfPaths.COMPATIBILITY_BLOCKS + ConfPaths.SUB_IGNOREPASSABLE, Arrays.asList( set(ConfPaths.COMPATIBILITY_BLOCKS + ConfPaths.SUB_IGNOREPASSABLE, Arrays.asList(
Material.WOODEN_DOOR.name(), Material.IRON_DOOR_BLOCK.name(), Material.WOODEN_DOOR.name(), Material.IRON_DOOR_BLOCK.name(),
Material.TRAP_DOOR.name(), Material.TRAP_DOOR.name(),