- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在学习计划任务。
基本上,我正在制作一个 Bukkit 插件,您可以在其中启用或禁用 PVP。当玩家输入/pvp on 或/pvp off 时,他们在 5 秒内不得移动,但是任务取消似乎并没有执行。
主类:
package me.mortadelle2.pvptoggle;
import java.util.ArrayList;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;
public class PVPToggle extends JavaPlugin {
ArrayList<String> noPVP = new ArrayList<String>();
HashMap<String, Boolean> hasMoved = new HashMap<String, Boolean>();
Player p;
public void onEnable() {
new PlayerDamage(this);
getLogger().info("PVPToggle toggled!");
}
public void onDisable() {
getLogger().info("PVPToggle disabled!");
}
public boolean onCommand(CommandSender sender, Command cmd, String label,
String[] args) {
p = (Player) sender;
if (cmd.getName().equalsIgnoreCase("pvp")) {
if (args.length == 0) {
p.sendMessage(ChatColor.RED + "Invalid usage! /pvp [on or off]");
return true;
}
if (args.length == 1) {
if (args[0].equalsIgnoreCase("on")) {
p.sendMessage(ChatColor.YELLOW
+ "PVP will be turned on in 5 seconds! Don't move!");
hasMoved.remove(p.getName());
hasMoved.put(p.getName(), false);
int turnOn = this.getServer().getScheduler()
.scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (hasMoved.get(p.getName()) == false) {
noPVP.remove(p.getName());
p.sendMessage(ChatColor.YELLOW
+ "You have turned PVP on!");
}
}
}, 100L);
if (hasMoved.get(p.getName()) == true) {
p.sendMessage(ChatColor.RED
+ "You moved so the action was cancelled.");
this.getServer().getScheduler().cancelTask(turnOn);
}
return true;
}
if (args[0].equalsIgnoreCase("off")) {
p.sendMessage(ChatColor.YELLOW
+ "PVP will be turned off in 5 seconds. Don't move!");
hasMoved.remove(p.getName());
hasMoved.put(p.getName(), false);
int turnOff = this.getServer().getScheduler()
.scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (hasMoved.get(p.getName()) == false) {
noPVP.add(p.getName());
p.sendMessage(ChatColor.YELLOW
+ "You have turned PVP off!");
}
}
}, 100L);
if (hasMoved.get(p.getName()) == true) {
p.sendMessage(ChatColor.RED
+ "You moved so the action was cancelled.");
this.getServer().getScheduler().cancelTask(turnOff);
}
return true;
}
}
}
return false;
}
}
监听器类:
package me.mortadelle2.pvptoggle;
import org.bukkit.Bukkit;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.util.Vector;
public class PlayerDamage implements Listener{
PVPToggle getter;
public PlayerDamage(PVPToggle plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
this.getter = plugin;
}
@EventHandler
public void playerJoins(PlayerJoinEvent e){
Player p = e.getPlayer();
getter.hasMoved.put(p.getName(), false);
}
@EventHandler
public void playerDamages(EntityDamageByEntityEvent e){
Player victim = (Player) e.getEntity();
Player killer = (Player) e.getDamager();
victim.sendMessage("hey");
if (getter.noPVP.contains(victim.getName()) || getter.noPVP.contains(killer.getName())){
e.setCancelled(true);
}
}
@EventHandler
public void playerShootsPlayer(EntityShootBowEvent e){
Arrow a = (Arrow) e.getEntity();
Player shooter = (Player) a.getShooter();
if (getter.noPVP.contains(a.getName()) || getter.noPVP.contains(shooter.getName())){
e.setCancelled(true);
}
}
@EventHandler
public void playerMoves(PlayerMoveEvent e) {
final Player p = e.getPlayer();
final Vector pVel = p.getVelocity();
getter.getServer().getScheduler()
.scheduleSyncDelayedTask(getter, new Runnable() {
@Override
public void run() {
if (pVel.getX() != 0 || pVel.getBlockY() != 0
|| pVel.getBlockZ() != 0) {
getter.hasMoved.remove(p.getName());
getter.hasMoved.put(p.getName(), true);
} else {
getter.hasMoved.remove(p.getName());
getter.hasMoved.put(p.getName(), false);
}
}
}, 5L);
}
}
最佳答案
没有必要取消任务,因为它已经结束了。我还发现您的代码存在一些问题。第一个也可能是最严重的问题是您在 PlayerMoveEvent 中安排任务,不仅如此,而且也是不必要的。使用该事件时您应该始终非常小心。每当玩家移动任何东西(包括他们的头部)时都会调用它。因此,该事件每秒可以调用数百次或数千次。如果不是绝对必要,您应该始终进行检查,以确保玩家移动到新 block 以减少代码运行的次数。一个更简单的方法就是做这样的事情:
@EventHandler
public void playerMoves(PlayerMoveEvent e) {
Player p = e.getPlayer();
//Check if the player moved to a new block
if (e.getTo().getBlockX() != e.getFrom().getBlockX() || e.getTo().getBlockY() != e.getFrom().getBlockY() || e.getTo().getBlockZ() != e.getFrom().getBlockZ()) {
//If they have, set their value in the hashmap to true
getter.hasMoved.put(p.getName(), true);
}
}
还要知道,您的调度程序仅在时间周期过去后调用一次,程序的其余部分将继续。您可以在调度程序中检查玩家是否已移动
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (hasMoved.get(p.getName()) == false) {
noPVP.remove(p.getName());
p.sendMessage(ChatColor.YELLOW + "You have turned PVP on!");
} else {
p.sendMessage(ChatColor.RED + "You moved so the action was cancelled.");
}
}
}, 100L);
还有一个简短的说明:每次更改玩家的值时,您不需要从 HashMap 中删除该玩家。 HashMap.put() 将覆盖现有值。
编辑(另一个建议):这可能是最好的方法,如果您想达到在玩家移动后立即向其发送取消消息的效果,您可以从 playerMoves
方法内部取消调度程序,而不是添加玩家到HashMap。这样,甚至不需要 HashMap,它只会提高整体代码质量。您确实应该尽可能避免使用 HashMap,通常有更好的方法。
关于java - 当 HashMap 值为 true 时任务不会被取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32273491/
我有不同的结构,它们都包含一个 HashMap与 String作为键,但具有不同的值类型。例如,一个结构有一个类型为 HashMap 的成员, 另一个将有一个 HashMap 类型的成员, 等等。 我
我想制作一个包含学生姓名和科目的板,每个学生在每个科目中都有一个成绩(或者没有..他可以离开考试而不写,然后他的案子将是空的)。我只想使用 HashMap。我的意思是,它会是这样的: HashMap>
是否有内存和速度高效的方法来在 HashMap 中动态存储唯一键:值对? key 保证是唯一的,但它们的数量经常变化。插入和删除必须很快。 我所做的是包含有符号距离场的八叉树(非线性/完整)。八叉树经
有谁知道为什么选择通过 LinkedList 而不是另一个 Hashmap 来实现 HashMap 的存储桶。如果桶本身变成了 HashMap,那么 contains 或 get 的时间复杂度似乎是
我想创建一个具有嵌套结构的 HashMap,就像这个复杂的示例: { type: boy name: Phineas father: type: man
这个问题在这里已经有了答案: How do I create a global, mutable singleton? (7 个答案) 关闭 7 年前。 我想要一个可扩展的字典,将 Object 与
HashMap> hm = new HashMap>(); hm.put("Title1","Key1"); for(int i=0;i hm1 = new H
我必须修改当前代码以适应 Spring MVC。我有 HashMap hashmap = new HashMap(); request.setAttribute("dslrErrors", hashm
我正在尝试进行一些错误捕获。 错误应该检查数组的长度是否小于 2,并检查 HashMap 是否包含用户输入的键。 捕获的错误必须仅使用 if 语句,并且必须使用 .length() 方法,并且必须使用
在 stackoverflow 上提出另一个问题后,(Java- Why this program not throwing concurrent Modification exception)我开始
我有两个类,想使用 org.dozer.Mapper( http://dozer.sourceforge.net/ ) 将 Female 对象的属性映射到 Male 对象。 第一类是: public
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be
是否有任何方法可以检查 HashMap 是否包含一组特定的键(这些键是在数组中给出的)。当我尝试类似下面的代码时,它返回 false。 map.containsKey(arrayOf("2018-01
跟进我的问题:How To Access hash maps key when the key is an object 我想尝试这样的事情:webSearchHash.put(xfile.getPa
我有一个可扩展的 ListView ,对于每个 child ,我需要有 4 个“额外”或字符串或其他名称来调用它:- 子标题- 描述- 链接1- 链接2 跟着教程,创建 ListView 、不同的 p
我想确保这是正确的,因为如果不正确,它可能会破坏我的应用程序。 我有这个: private static HashMap> balance = new HashMap<>(); 如果我得到这样的值:
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我是一名优秀的程序员,十分优秀!