Last active
November 6, 2016 10:59
-
-
Save aadnk/4448838 to your computer and use it in GitHub Desktop.
Anti-wall jumping protection. Just a test, though.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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