Skip to content

Instantly share code, notes, and snippets.

@aadnk
Last active November 6, 2016 10:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aadnk/4448838 to your computer and use it in GitHub Desktop.
Save aadnk/4448838 to your computer and use it in GitHub Desktop.
Anti-wall jumping protection. Just a test, though.
/*
* TestMod - A simple attempt at preventing laggy wall jumping.
* Copyright (C) 2012 Kristian S. Stangeland
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version 2 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 Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.testlag;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
import net.minecraft.server.v1_4_6.EntityPlayer;
import net.minecraft.server.v1_4_6.NetworkManager;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v1_4_6.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.common.collect.Sets;
public class TestMod extends JavaPlugin implements Listener {
public class TemporaryStore<T> {
private Set<T> primary = Sets.newSetFromMap(new WeakHashMap<T, Boolean>());
private Set<T> secondary = Sets.newSetFromMap(new WeakHashMap<T, Boolean>());
private final long timeout;
// The time to swap sets and clean out old entires
private long swapTime;
/**
* Initialize a new store of temporary values.
* <p>
* Entries are guaranteed to be removed after 2*timeout milliseconds.
*
* @param timeout - the minimum number of milliseconds to wait until removing old entries.
*/
public TemporaryStore(long timeout) {
this.timeout = timeout;
checkSwapRemove();
}
/**
* Add a given entry to the store.
* @param entry - the entry to add.
*/
public void add(T entry) {
checkSwapRemove();
primary.add(entry);
}
public boolean contains(T entry) {
checkSwapRemove();
return primary.contains(entry) || secondary.contains(entry);
}
private void checkSwapRemove() {
long current = System.currentTimeMillis();
if (current > swapTime) {
secondary.clear();
swapSets();
swapTime = current + timeout * 2;
}
}
private void swapSets() {
Set<T> temp = primary;
primary = secondary;
secondary = temp;
}
public long getTimeout() {
return timeout;
}
}
private Set<String> disableAll = new HashSet<String>();
// Temporary cache of cancelled blocks
private TemporaryStore<Location> cancelledBlocks = new TemporaryStore<Location>(30 * 1000);
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
if (disableAll.contains(player.getName())) {
cancelledBlocks.add(event.getBlock().getLocation());
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerMovement(PlayerMoveEvent event) {
Location to = event.getTo();
int x = to.getBlockX();
int y = to.getBlockY();
int z = to.getBlockZ();
// Possible location
Location likelyCandidate = new Location(to.getWorld(), x, y - 1, z);
// Search in a 9x9 area
for (int dX = -1; dX < 2; dX++) {
for (int dZ = -1; dZ < 2; dZ++) {
likelyCandidate.setX(x + dX);
likelyCandidate.setZ(z + dZ);
if (cancelledBlocks.contains(likelyCandidate)) {
// Teleport to spawn
event.getPlayer().teleport(event.getPlayer().getCompassTarget());
return;
}
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerQuit(PlayerQuitEvent event) {
disableAll.remove(event.getPlayer().getName());
}
private boolean toggleProtection(Player player) {
String name = player.getName();
// If we weren't disabled, add us
if (!disableAll.remove(name)) {
disableAll.add(name);
return true;
} else {
return false;
}
}
public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {
Player target = null;
LinkedList<String> arguments = new LinkedList<String>(Arrays.asList(args));
// ToDo: Better system
int subArgument = command.getLabel().equals("protection") ? 0 : 1;
// Error checking
if (args.length == subArgument) {
if (sender instanceof Player)
target = (Player) sender;
else
sender.sendMessage(ChatColor.RED + "No player supplied.");
} else if (args.length == subArgument + 1) {
target = getServer().getPlayer(arguments.poll());
if (target == null)
sender.sendMessage(ChatColor.RED + "Cannot find player " + args[0]);
} else {
sender.sendMessage(ChatColor.RED + "Too many arguments.");
return false;
}
if (command.getLabel().equals("protection"))
commandProtection(sender, target, arguments);
else if (command.getLabel().equals("setlag"))
commandSetLag(sender, target, arguments);
else
return false;
// Command syntax is correct
return true;
}
private void commandSetLag(CommandSender sender, Player target, List<String> arguments) {
EntityPlayer ep = ((CraftPlayer) target).getHandle();
NetworkManager nm = (NetworkManager) ep.playerConnection.networkManager;
try {
int lag = Integer.parseInt(arguments.get(0));
if (lag >= 0) {
nm.e = lag;
sender.sendMessage(ChatColor.BLUE + "Set lag for " + target.getDisplayName() + " to " + lag + " ms");
} else {
sender.sendMessage(ChatColor.RED + "Lag cannot be a negative number.");
}
} catch (NumberFormatException e) {
sender.sendMessage(ChatColor.RED + "The paramater " + arguments.get(0) + " is not a number.");
}
}
public void commandProtection(CommandSender sender, Player target, List<String> arguments) {
// Perform action if successful
if (target != null) {
if (toggleProtection(target))
sender.sendMessage(ChatColor.BLUE + "Enabled protection.");
else
sender.sendMessage(ChatColor.BLUE + "Disabled protection.");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment