takepansan さんが書きました:ExampleTask().runTaskLaterを使用するときに,Mainクラス以外で使うとnew ExampleTask().runTaskLater(this ,100);でエラーが出ます。解決方法はありますか?
/* Mainクラス */
private static Main i;
@Override
public void onEnable(){
i = this;
}
public static Main getInstance(){
return i;
}
/* 別のクラス */
public void delayTaskTest(){
Main i = Main.getInstance();
Bukkit.getScheduler().runTaskLater(i, new Runnable(){});
}
TA3 さんが書きました:takepansan さんが書きました:ExampleTask().runTaskLaterを使用するときに,Mainクラス以外で使うとnew ExampleTask().runTaskLater(this ,100);でエラーが出ます。解決方法はありますか?
JavaPluginを継承しているクラス以外ではPluginのparamとして自クラスのインスタンスを使用することができません。
javaPluginを継承しているMainクラスのインスタンスを保持してそれを使います。
- コード: 全て選択
/* Mainクラス */
private static Main i;
@Override
public void onEnable(){
i = this;
}
public static Main getInstance(){
return i;
}
/* 別のクラス */
public void delayTaskTest(){
Main i = Main.getInstance();
Bukkit.getScheduler().runTaskLater(i, new Runnable(){});
}
private int counter;
@EventHandler
public void onWeapon(PlayerInteractEvent e){
Material m = e.getItem().getType();
ItemStack itemStack = e.getItem();
if(m == Material.STICK && itemStack.hasItemMeta() == true && e.getAction() == Action.RIGHT_CLICK_AIR ){
counter = 5;
new WeaponTask(this, counter ,e.getPlayer()).runTaskTimer(this, 0, 5);
}
}
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class WeaponTask extends BukkitRunnable{
private final JavaPlugin plugin;
private int counter;
private Player player;
public WeaponTask(JavaPlugin plugin, int counter , Player player){
this.plugin = plugin;
if(counter < 1){
throw new IllegalArgumentException("counter には1以上を指定してください。");
}
else{
this.player = player;
this.counter = counter;
}
}
@SuppressWarnings("deprecation")
@Override
public void run(){
if(counter > 0){
player.throwSnowball();
player.playSound(player.getLocation(), Sound.BLAZE_HIT, 10, 10);
counter--;
}
else{
plugin.getServer().broadcastMessage("ラストカウンター: " + counter);
plugin.getServer().broadcastMessage("END");
this.cancel();
}
}
八咫烏 さんが書きました:MainClass↓
- コード: 全て選択
private int counter;
@EventHandler
public void onWeapon(PlayerInteractEvent e){
Material m = e.getItem().getType();
ItemStack itemStack = e.getItem();
if(m == Material.STICK && itemStack.hasItemMeta() == true && e.getAction() == Action.RIGHT_CLICK_AIR ){
counter = 5;
new WeaponTask(this, counter ,e.getPlayer()).runTaskTimer(this, 0, 5);
}
}
サブクラス↓
- コード: 全て選択
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class WeaponTask extends BukkitRunnable{
private final JavaPlugin plugin;
private int counter;
private Player player;
public WeaponTask(JavaPlugin plugin, int counter , Player player){
this.plugin = plugin;
if(counter < 1){
throw new IllegalArgumentException("counter には1以上を指定してください。");
}
else{
this.player = player;
this.counter = counter;
}
}
@SuppressWarnings("deprecation")
@Override
public void run(){
if(counter > 0){
player.throwSnowball();
player.playSound(player.getLocation(), Sound.BLAZE_HIT, 10, 10);
counter--;
}
else{
plugin.getServer().broadcastMessage("ラストカウンター: " + counter);
plugin.getServer().broadcastMessage("END");
this.cancel();
}
}
これで、スノーボール発射するんですけど、右クリックで連射中にもう一度右クリックすると
かぶせて発射されてしまいます(2回分サブクラスが働く)
こうしないためにはどうすればいいんでしょうか。
public List<UUID> list = new ArrayList<UUID>();
@EventHandler
public void onWeapon(PlayerInteractEvent e){
Player p = e.getPlayer();
UUID uuid = p.getUniqueId();
ItemStack itemStack = e.getItem();
if(e.getAction() == Action.RIGHT_CLICK_AIR && !list.contains(uuid) && itemStack.hasItemMeta() && itemStack.getType == Material.STICK){
new WeaponTask(this, 5 , p).runTaskTimer(this, 0, 5);
list.add(uuid);
}
}
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class WeaponTask extends BukkitRunnable{
private final JavaPlugin plugin;
private int counter;
private Player player;
public WeaponTask(JavaPlugin plugin, int counter , Player player){
if(counter > 0){
this.plugin = plugin;
this.player = player;
this.counter = counter;
}else{
throw new IllegalArgumentException("counter には1以上を指定してください。");
}
}
@SuppressWarnings("deprecation")
@Override
public void run(){
if(counter > 0){
player.throwSnowball();
//throwSnowball():これはコードを省略されただけでしょうか…?
player.playSound(player.getLocation(), Sound.BLAZE_HIT, 10, 10);
counter--;
}else{
plugin.getServer().broadcastMessage("ラストカウンター: " + counter);
plugin.getServer().broadcastMessage("END");
plugin.list.remove(player.getUniqueId());
this.cancel();
}
}
amata1219 さんが書きました:八咫烏 さんが書きました:MainClass↓
- コード: 全て選択
private int counter;
@EventHandler
public void onWeapon(PlayerInteractEvent e){
Material m = e.getItem().getType();
ItemStack itemStack = e.getItem();
if(m == Material.STICK && itemStack.hasItemMeta() == true && e.getAction() == Action.RIGHT_CLICK_AIR ){
counter = 5;
new WeaponTask(this, counter ,e.getPlayer()).runTaskTimer(this, 0, 5);
}
}
サブクラス↓
- コード: 全て選択
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class WeaponTask extends BukkitRunnable{
private final JavaPlugin plugin;
private int counter;
private Player player;
public WeaponTask(JavaPlugin plugin, int counter , Player player){
this.plugin = plugin;
if(counter < 1){
throw new IllegalArgumentException("counter には1以上を指定してください。");
}
else{
this.player = player;
this.counter = counter;
}
}
@SuppressWarnings("deprecation")
@Override
public void run(){
if(counter > 0){
player.throwSnowball();
player.playSound(player.getLocation(), Sound.BLAZE_HIT, 10, 10);
counter--;
}
else{
plugin.getServer().broadcastMessage("ラストカウンター: " + counter);
plugin.getServer().broadcastMessage("END");
this.cancel();
}
}
これで、スノーボール発射するんですけど、右クリックで連射中にもう一度右クリックすると
かぶせて発射されてしまいます(2回分サブクラスが働く)
こうしないためにはどうすればいいんでしょうか。
八咫烏さん、こんにちは。
それでしたら、ループ処理中か確認するコードを追加するだけで簡単に解決出来ます。
1. Mainクラスにpublic List<UUID>を作成(ここでは変数名listとします)。
2. Main#onWeapon(…)のif文に、!list.contains(e.getPlayer().getUniqueId())の条件文を追加。
3. Main#onWeapon(…)でのWeaponTask生成後にlist.add(e.getPlayer().getUniqueId())の記述を追加。
4. WeaponTask#run()のbroadcastMessage("END")の後に、plugin.list.remove(player.getPlayer().getUniqueId())の記述を追加。
Main.class
- コード: 全て選択
public List<UUID> list = new ArrayList<UUID>();
@EventHandler
public void onWeapon(PlayerInteractEvent e){
Player p = e.getPlayer();
UUID uuid = p.getUniqueId();
ItemStack itemStack = e.getItem();
if(e.getAction() == Action.RIGHT_CLICK_AIR && !list.contains(uuid) && itemStack.hasItemMeta() && itemStack.getType == Material.STICK){
new WeaponTask(this, 5 , p).runTaskTimer(this, 0, 5);
list.add(uuid);
}
}
WeaponTask.class
- コード: 全て選択
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class WeaponTask extends BukkitRunnable{
private final JavaPlugin plugin;
private int counter;
private Player player;
public WeaponTask(JavaPlugin plugin, int counter , Player player){
if(counter > 0){
this.plugin = plugin;
this.player = player;
this.counter = counter;
}else{
throw new IllegalArgumentException("counter には1以上を指定してください。");
}
}
@SuppressWarnings("deprecation")
@Override
public void run(){
if(counter > 0){
player.throwSnowball();
//throwSnowball():これはコードを省略されただけでしょうか…?
player.playSound(player.getLocation(), Sound.BLAZE_HIT, 10, 10);
counter--;
}else{
plugin.getServer().broadcastMessage("ラストカウンター: " + counter);
plugin.getServer().broadcastMessage("END");
plugin.list.remove(player.getUniqueId());
this.cancel();
}
}
1~4に従いコードを記述するとこのようになると思います。1~4以外で個人的に気になる点がいくつかありましたので合わせて修正させて頂きました。
a: Main#counter - 必要無いのでnew WeaponTask(…)に数値をそのまま記述(呼び出し元でメソッドの引数に基本データ型を使用した場合、メソッドではその値のコピーを受け取ります。単純に値のコピーを渡しているだけなので、メソッド内でその値に変更を加えても、呼び出し元には影響しません)。
b: Main#onWeapon(…) - if文の条件「itemStack.hasItemMeta()がtrue」は==trueを記述する必要無し(代入と見間違えたり、コードが冗長になるため)。
c: WeaponTask#WeaponTask - 条件は分かりやすくrun()と同じ記述にし、最初の代入処理(this.plugin = plugin;)はif文内に他の代入処理と一緒に記述。
追記:
後々思いつきましたがループ処理の終了時間が分かっているなら、onWeapon(…)でlist.remove(uuid)を遅延実行処理するという方法もあります(というかこちらの方が楽)。
八咫烏 さんが書きました:詰まってしまって、たびたび質問失礼します。
(上記コード参照)
銃を打つ(雪玉を発射する)たびに残りの弾数表示をItemDisplayNameに表示させたいんですけど
Mainクラスでのアイテムの名前変更はできるんですけど
このMainクラスで取得したアイテムスタックをサブクラスに渡して
サブクラスでそのitemmetaを設定しSetItemmetaをした際に
名前の変更が表示されません。(サブクラスに渡している時点でItemStackが別物として扱われるのでしょうか)
よろしくお願いします。
package amata1219.check;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
public class Check extends JavaPlugin implements Listener{
@Override
public void onEnable(){
getServer().getPluginManager().registerEvents(this, this);
}
@Override
public void onDisable(){
}
@EventHandler
public void onInteract(PlayerInteractEvent e){
ItemStack item = e.getItem();
if(item != null && item.getType() != Material.AIR){
setMeta(item);
System.out.println(item.getItemMeta().getDisplayName());
new SubCheck().setMeta(item);
System.out.println(item.getItemMeta().getDisplayName());
SubCheck.setMetaa(item);
System.out.println(item.getItemMeta().getDisplayName());
}
}
public void setMeta(ItemStack item){
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("GRASS");
item.setItemMeta(meta);
}
}
package amata1219.check;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class SubCheck {
public void setMeta(ItemStack item){
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("DIRT");
item.setItemMeta(meta);
}
public static void setMetaa(ItemStack item){
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("PODZOL");
item.setItemMeta(meta);
}
}
[17:25:43] [Server thread/INFO]: GRASS
[17:25:43] [Server thread/INFO]: DIRT
[17:25:43] [Server thread/INFO]: PODZOL
CYBORG さんが書きました:特定の剣(アイテム)にエフェクトを追加したいんですが、詰まってしまってできません。
Gattino さんが書きました:私は今1.13MinecrafSpigotプラグインを自作しています。
ですが、試しに動作確認をしようとMavenプロジェクトでビルドして、できた.jarファイルをpluginsフォルダに入れてサーバーを起動したのですが、プラグインが適用されません。
赤く表示すらされません。
ほかのプラグインは表示されているのに、自作のものだけが表示されないんです。
どこに問題があるのでしょうか、調べるべき点、原因として考えられる可能性がある事象を教えてください。よろしくお願いします。
ちなみにeclipseを使用しています。
amata1219 さんが書きました:Gattino さんが書きました:私は今1.13MinecrafSpigotプラグインを自作しています。
ですが、試しに動作確認をしようとMavenプロジェクトでビルドして、できた.jarファイルをpluginsフォルダに入れてサーバーを起動したのですが、プラグインが適用されません。
赤く表示すらされません。
ほかのプラグインは表示されているのに、自作のものだけが表示されないんです。
どこに問題があるのでしょうか、調べるべき点、原因として考えられる可能性がある事象を教えてください。よろしくお願いします。
ちなみにeclipseを使用しています。
Gattinoさん、こんにちは。
エラーすら表示されないとなると、plugin.ymlがプラグインに含まれていないのかもしれません。
Mavenプロジェクトでresourcesにplugin.ymlを入れている場合、エクスポートでなくMavenプロジェクト→右クリック→実行→Maven installを選択し、workspace/プラグイン名/targetに生成されるjarファイルを導入してみて下さい。
@EventHandler
public void OnClick(InventoryClickEvent e){
// 1ページ目のクリックイベント
if(e.getClickedInventory().getName().equals("§e[§a§lCommand§6§lGUI§e]§d||§6§l1ページ目§d||") == true){
// ページ変更 イベント設定
if(e.getCurrentItem().getType()== Material.DOUBLE_PLANT && e.getSlot() == 53){
Player p = (Player)e.getWhoClicked();
// {{ ここに書く予定です }}
}
}
}
testusuke さんが書きました:【プラグイン開発】インベントリクリックイベントでの、コマンドを実行させる方法
こんにちは。プラグイン開発をしています。
そこで今困ってることがあります。インベントリGUIを作成して、onClickイベントで指定したアイテムをクリックすると、プレイヤーにコマンドを実行させる方法がわかりません。わかる方教えてください。
ソースコード 「{{ ここに書く予定です }}」というとこに書く予定です
- コード: 全て選択
@EventHandler
public void OnClick(InventoryClickEvent e){
// 1ページ目のクリックイベント
if(e.getClickedInventory().getName().equals("§e[§a§lCommand§6§lGUI§e]§d||§6§l1ページ目§d||") == true){
// ページ変更 イベント設定
if(e.getCurrentItem().getType()== Material.DOUBLE_PLANT && e.getSlot() == 53){
Player p = (Player)e.getWhoClicked();
// {{ ここに書く予定です }}
}
}
}
付け足し
イベントリGUIのあるアイテムをクリックすると、そのプレーヤーがコマンドを自動的に実行するという形です。
早めの回答お待ちしております!
Bukkit.dispatchCommand(p, "COMMAND_HERE"); // コマンドをプレイヤーに実行させる
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "COMMAND_HERE"); // コンソールからコマンドを実行する
ryotaa さんが書きました:プラグインを作っています。
特定のプレイヤーの入っているチームを取得する方法を教えてください。
viewtopic.php?f=39&t=8371&start=600
ここのPostNo.172544でPlayerから直接チームを取得できないと書いてあったのですが、
そのスレを見てもじゃあどうやってチームを取得するかわからなかったので質問させていただきました。