Skip to content

Instantly share code, notes, and snippets.

@WouterG
Last active July 31, 2019 15:46
Show Gist options
  • Save WouterG/94070d1a2de8e63ed711e8cc43889d17 to your computer and use it in GitHub Desktop.
Save WouterG/94070d1a2de8e63ed711e8cc43889d17 to your computer and use it in GitHub Desktop.
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.menoni.rd.RuntimeDebugger;
import net.menoni.rd.model.Debugger;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.scheduler.BukkitTask;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
public class Speedometer implements Debugger, Debugger.Stoppable, Listener, Runnable {
private static Player p;
private BukkitTask updateTaskIdle;
private Map<UUID, Long> lastUpdateMap = new ConcurrentHashMap<>();
private static Map<Double, SpeedDef> speedDefs = new ConcurrentHashMap<>();
private static SpeedDef defaultSpeedDef = new SpeedDef("Idle", ChatColor.WHITE);
private static long fastedSpeedUpdateTime = 0;
private static double fastestSpeedLast5Sec = 0.0d;
private static class SpeedDefRes {
private SpeedDef def;
private boolean over;
private boolean close;
public SpeedDefRes(SpeedDef def, boolean over, boolean close) {
this.def = def;
this.over = over;
this.close = close;
}
public SpeedDef getDef() {
return def;
}
public boolean isOver() {
return over;
}
public boolean isClose() {
return close;
}
}
private static class SpeedDef {
private String name;
private ChatColor color;
private Function<Player, Boolean> condition;
public SpeedDef(String name, ChatColor color) {
this.name = name;
this.color = color;
}
public SpeedDef(String name, ChatColor color, Function<Player, Boolean> condition) {
this.name = name;
this.color = color;
this.condition = condition;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ChatColor getColor() {
return color;
}
public void setColor(ChatColor color) {
this.color = color;
}
public Function<Player, Boolean> getCondition() {
return condition;
}
public void setCondition(Function<Player, Boolean> condition) {
this.condition = condition;
}
}
@Override
public void debug(RuntimeDebugger plugin, CommandSender cs) {
if (!(cs instanceof Player)) {
cs.sendMessage("Need to be player");
return;
}
this.initSpeedNames();
this.p = (Player) cs;
this.updateTaskIdle = Bukkit.getScheduler().runTaskTimer(plugin, this, 4L, 4L);
}
private void initSpeedNames() {
speedDefs.put(0.0d, defaultSpeedDef);
speedDefs.put(1.31d, new SpeedDef("Sneaking", ChatColor.GRAY));
speedDefs.put(4.317d, new SpeedDef("Walking", ChatColor.AQUA));
speedDefs.put(5.612d, new SpeedDef("Sprinting", ChatColor.DARK_AQUA));
speedDefs.put(7.0d, new SpeedDef("Minecart", ChatColor.GREEN));
speedDefs.put(8.0d, new SpeedDef("Minecart", ChatColor.DARK_GREEN));
speedDefs.put(11.314d, new SpeedDef("Diagonal Minecart", ChatColor.YELLOW));
speedDefs.put(30.0d, new SpeedDef("0° Elytra Glide", ChatColor.GOLD));
speedDefs.put(33.5d, new SpeedDef("Elytra Rocket Boost", ChatColor.RED));
speedDefs.put(40.0d, new SpeedDef("Ice Boat", ChatColor.DARK_RED));
speedDefs.put(70.0d, new SpeedDef("Blue Ice Boat", ChatColor.DARK_GRAY));
speedDefs.put(67.3d, new SpeedDef("52° Elytra Turbo!", ChatColor.BLACK));
}
@Override
public void stop() {
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.getUniqueId().equals(p.getUniqueId())) {
onlinePlayer.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(""));
}
}
this.updateTaskIdle.cancel();
}
@Override
public void run() {
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.getUniqueId().equals(p.getUniqueId())) {
Long time = lastUpdateMap.get(onlinePlayer.getUniqueId());
if (time != null && time + 500 > System.currentTimeMillis()) {
continue;
}
p.spigot().sendMessage(ChatMessageType.ACTION_BAR, buildMessage(0d));
}
}
}
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if (p == null) {
return;
}
if (event.getFrom() == null || event.getTo() == null || event.getPlayer() == null) {
return;
}
// debug
if (!event.getPlayer().getUniqueId().equals(p.getUniqueId())) {
return;
}
double speed = getDistanceFast(
event.getFrom().getX(),
event.getFrom().getY(),
event.getFrom().getZ(),
event.getTo().getX(),
event.getTo().getY(),
event.getTo().getZ()
);
speed *= 20; // blocks per ticks -> seconds
event.getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, buildMessage(speed));
lastUpdateMap.put(event.getPlayer().getUniqueId(), System.currentTimeMillis());
}
private static SpeedDefRes getSpeedDef(double speed) {
double nearestKey = 0;
Double closestKey = null;
for (Double key : speedDefs.keySet()) {
if (key > nearestKey && key <= speed) {
nearestKey = key;
}
if (Math.abs(key - speed) < 0.25) {
closestKey = key;
}
}
SpeedDef def = speedDefs.get(nearestKey);
def = def == null ? defaultSpeedDef : def;
boolean over = false;
if (nearestKey < speed) {
over = true;
}
return new SpeedDefRes(def, over, closestKey != null);
}
public static BaseComponent buildMessage(double speed) {
if (fastedSpeedUpdateTime + 5000 < System.currentTimeMillis()) {
p.sendMessage("Fastest 5-sec speed: " + fastestSpeedLast5Sec);
fastestSpeedLast5Sec = 0;
fastedSpeedUpdateTime = System.currentTimeMillis();
}
if (speed > fastestSpeedLast5Sec) {
fastestSpeedLast5Sec = speed;
}
SpeedDefRes speedDef = getSpeedDef(speed);
TextComponent base = new TextComponent("Speed: ");
base.setColor(ChatColor.YELLOW.asBungee());
TextComponent speedPart = new TextComponent(String.format("%.3f", speed));
speedPart.setColor(speedDef.getDef().getColor().asBungee());
base.addExtra(speedPart);
TextComponent unitPart = new TextComponent(" b/s");
unitPart.setColor(ChatColor.YELLOW.asBungee());
base.addExtra(unitPart);
// if (speedDef.isClose()) {
// TextComponent namePart = new TextComponent(" " + speedDef.getDef().getName() + (speedDef.isOver() ? "+" : ""));
// namePart.setColor(ChatColor.YELLOW.asBungee());
// base.addExtra(namePart);
// }
return base;
}
public static double getDistanceFast(double x1, double y1, double z1, double x2, double y2, double z2) {
double dx = (x1 - x2);
double dy = (y1 - y2);
double dz = (z1 - z2);
return Math.sqrt(dx*dx + dy*dy + dz*dz);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment