【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

フォーラムルール
質問関連フォーラムで質問する時は、必ず次のトピックを一読/厳守お願い致します。
viewtopic.php?f=5&t=999

返信する

:
不正プログラムによるアクセスを防ぐため、reCaptcha 認証コードの入力を強制しています。表示されている 2 つのワードをテキストフィールドにご入力ください。

BBCode: OFF
スマイリー: OFF
トピックのレビュー
   

ファイルを添付します

展開ビュー トピックのレビュー: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by AKM » 2017年9月16日(土) 22:27

丁寧な解説ありがとうございます。
提示していただいた例とサイトを使って頑張って見ます。
ありがとうございました!

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by amata1219 » 2017年9月16日(土) 19:52

AKM さんが書きました:質問なのですが、アイテム(剣、斧などの武器)の攻撃速度や攻撃威力を変更することは不可能なのでしょうか。
ItemMetaからは変更できそうになく、海外のサイトで検索をかけても旧バージョンの方法しか出てきません。
APIの変更で設定できなくなってしまったのでしょうか。
方法を知っている方教えてください。よろしくお願いします。
(spigot-ver-1.12.1)


AKMさんこんにちは。
結論から申し上げますと可能です。
ご存知でしたら申し訳ございませんが、攻撃速度や攻撃威力はAttribute ModifiersというNBTタグの一種であり、ItemMetaからの読み書きは出来ません。
そこで、プラグインからのAttribute Modifiers及びNBTの読み書きにはNMSを利用します。
下記コードは攻撃力+50の木の剣をプレイヤーに与えるコードになります。
コメントアウト部の解説と合わせてご参考にして頂ければと思います。
コード: 全て選択
      ItemStack item = new ItemStack(Material.WOOD_SWORD);
      //新しいアイテムを作成。

      net.minecraft.server.v1_12_R1.ItemStack nmsItem= CraftItemStack.asNMSCopy(item);
      //CraftItemStackクラスのasNMSCopyメソッドでnmsItemStackを取得する。

      NBTTagCompound compound = (nmsItem.hasTag()) ? nmsItem.getTag() : new NBTTagCompound();
      //NMSのItemStackコンパウンドはnullに出来るので確認する。

      NBTTagList modifiers = new NBTTagList();
      //書き込む属性を入れるリストを作成する。

      NBTTagCompound dmg = new NBTTagCompound();
      //attackDamage属性を編集するための変数を作成する。

      dmg.set("AttributeName", new NBTTagString("generic.attackDamage"));
      dmg.set("Name", new NBTTagString("generic.attackDamage"));
      //属性を指定する。名称は公式Wikiを参考にしました。

      dmg.set("Amount", new NBTTagInt(50));
      //ここでダメージ量を指定出来ます。ここでの数値1はハート0.5に値します。

      dmg.set("Operation", new NBTTagInt(0));
      //属性の基本値を編集出来ますが基本触らないため0を指定します。

      dmg.set("UUIDLeast", new NBTTagInt(894654));
      dmg.set("UUIDMost", new NBTTagInt(2872));
      //ここの2つは恐らく触ってはいけません。数値は公式Wikiを参考にしました。

      dmg.set("Slot", new NBTTagString("mainhand"));
      //ここでAttributeModifiers効果を有効にするスロットを指定します。指定しないと全スロットで有効になります。

      modifiers.add(dmg);
      //リストに書き込む。

      compound.set("AttributeModifiers", modifiers);
      //nmsItemStackから取得したItemStackコンパウンドに書き込む。

      nmsItem.setTag(compound);
      //アイテムにNBTを書き込む。

      item = CraftItemStack.asBukkitCopy(nmsItem);
      //CraftItemStackクラスのasBukkitCopyメソッドにNBTTag書き込み済みのnmsItemStackを入れる。

      p.getInventory().addItem(item);
      //プレイヤーにアイテムを与える


参考にした記事:
Minecraft公式Wiki - Attribute
またVer.1.11で英語ではありますがAtturibute Modifiersに関連するチュートリアルを見つけましたので記載させて頂きますね。
NBTTags & Attribute チュートリアル

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by AKM » 2017年9月15日(金) 17:04

質問なのですが、アイテム(剣、斧などの武器)の攻撃速度や攻撃威力を変更することは不可能なのでしょうか。
ItemMetaからは変更できそうになく、海外のサイトで検索をかけても旧バージョンの方法しか出てきません。
APIの変更で設定できなくなってしまったのでしょうか。
方法を知っている方教えてください。よろしくお願いします。
(spigot-ver-1.12.1)

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by ことむー » 2017年9月14日(木) 23:55

hyoreo さんが書きました:
amata1219 さんが書きました:

King(qpwakaba) さんが書きました:

ご回答ありがとうございます。
早速書いてみようと思ったのですが、
連射を止める条件をどうやって検知するのかがわかりません。。。
isBlocking()で右クリックを押しているか検知できるかと思ったのですが、できませんでした・・・
プレイヤーが右クリックしているか確認する関数は存在するのでしょうか?


横から失礼( ´_ゝ`)ノ
もし1tickごとに連射っていう感じでやりたいのであれば
右クリックイベント(PlayerInteractEvent)は1/4秒(5tick)間隔で動いてるので
InteractEventが発生

適当な変数に5を代入

タイマーが動くたびに変数をデクリメント(減算)

その変数が0以下になった場合は連射を止める

って感じの処理でやると良いんでないかな?
まぁ後は工夫して自分のやりやすいように頑張って!(´-ω-`)(雑

昔自分もKing氏に同じような動作アドバイスしてもらった
以下それっぽい動きのやつ、可変可能
https://github.com/kotmw0701/Splatoon-i ... ooter.java

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by hyoreo » 2017年9月14日(木) 23:33

amata1219 さんが書きました:

King(qpwakaba) さんが書きました:

ご回答ありがとうございます。
早速書いてみようと思ったのですが、
連射を止める条件をどうやって検知するのかがわかりません。。。
isBlocking()で右クリックを押しているか検知できるかと思ったのですが、できませんでした・・・
プレイヤーが右クリックしているか確認する関数は存在するのでしょうか?

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by amata1219 » 2017年9月11日(月) 22:29

King(qpwakaba) さんが書きました:
amata1219 さんが書きました:
hyoreo さんが書きました:

多分連射速度、という意味だと思うんで簡単に方法だけ

最初にInteractEventで スケジューラタスクを開始

連射を止める条件を満たすまで、スケジューラタスクでたまを発射し続ける

連射を止める条件を満たしたら、スケジューラタスクを止める


連射中に速度が変わらなければrunTaskTimerを使うと良いかも。
連射中に速度を変えたいのであれば、runTaskLaterを使って、タスクの中でrunTaskLaterするといいかも。

ああ、そういう事でしたか。誤解していました…_(:3 ∠ )_。
付け足しありがとうございます。

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by King(qpwakaba) » 2017年9月11日(月) 21:56

amata1219 さんが書きました:
hyoreo さんが書きました:

多分連射速度、という意味だと思うんで簡単に方法だけ

最初にInteractEventで スケジューラタスクを開始

連射を止める条件を満たすまで、スケジューラタスクでたまを発射し続ける

連射を止める条件を満たしたら、スケジューラタスクを止める


連射中に速度が変わらなければrunTaskTimerを使うと良いかも。
連射中に速度を変えたいのであれば、runTaskLaterを使って、タスクの中でrunTaskLaterするといいかも。

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by amata1219 » 2017年9月11日(月) 21:39

hyoreo さんが書きました:質問です。
名前の付いた特定のアイテムを右クリックすると雪玉が発射されるプラグインを作っていて、
PlayerInteractEventが発生するたびに雪玉を発射する処理を作ってみたのですが、
この方法だと弾が出る頻度を遅くしたり早くしたりすることができず困っています。
スケジューラを使ってなんとかしようとしたけどうまくいかず・・・orz
何かいい方法があればご教示ください!

コードです↓
コード: 全て選択
   String weapon;

   String gun = "銃";

   @EventHandler
   public void onPlayerInteractEvent(PlayerInteractEvent event) {
      if (!event.hasItem()) return;
      ItemStack playeritem = event.getPlayer().getItemInHand();
      if (!playeritem.hasItemMeta()) return;
      if (!event.getAction().equals(Action.RIGHT_CLICK_AIR) ||
         !event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return;
      if (playeritem.getItemMeta().getDisplayName().equals(gun)) {
         if (playeritem.getType().equals(Material.IRON_BARDING)){
            event.getPlayer().launchProjectile(Snowball.class);
         }
      }
   }


hyoreoさんこんばんは。
雪玉発射処理を遅延実行したいのであればスケジューラを用いるだけで可能でして、以下の様にするだけで遅延実行出来ます。
コード: 全て選択
new BukkitRunnable(){
public void run(){
//ここに遅延実行したい処理を記述
}
}.runTaskLater(plugin, tick)

一応チュートリアルのURLも貼らせて頂きますね。
スケジューラのプログラミング

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by hyoreo » 2017年9月11日(月) 16:27

質問です。
名前の付いた特定のアイテムを右クリックすると雪玉が発射されるプラグインを作っていて、
PlayerInteractEventが発生するたびに雪玉を発射する処理を作ってみたのですが、
この方法だと弾が出る頻度を遅くしたり早くしたりすることができず困っています。
スケジューラを使ってなんとかしようとしたけどうまくいかず・・・orz
何かいい方法があればご教示ください!

コードです↓
コード: 全て選択
   String weapon;

   String gun = "銃";

   @EventHandler
   public void onPlayerInteractEvent(PlayerInteractEvent event) {
      if (!event.hasItem()) return;
      ItemStack playeritem = event.getPlayer().getItemInHand();
      if (!playeritem.hasItemMeta()) return;
      if (!event.getAction().equals(Action.RIGHT_CLICK_AIR) ||
         !event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return;
      if (playeritem.getItemMeta().getDisplayName().equals(gun)) {
         if (playeritem.getType().equals(Material.IRON_BARDING)){
            event.getPlayer().launchProjectile(Snowball.class);
         }
      }
   }

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by miyabi » 2017年8月31日(木) 17:01

Pucian さんが書きました:いきなりですみません。 チャット発言時に名前の横にマインクラフトのレベルを表示させるプラグインはありますか?
探しても見つからないんです。

質問:開発・制作関連
【総合】トピック立てるまでもない質問【Bukkit Plugin制作

カテゴリ名やトピック名は良く読んで投稿するようにしましょう。
削除依頼、移動依頼は以下からどうぞ。
viewtopic.php?f=16&t=3583

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by Pucian » 2017年8月31日(木) 16:53

いきなりですみません。 チャット発言時に名前の横にマインクラフトのレベルを表示させるプラグインはありますか?
探しても見つからないんです。

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by カーボンファイバー » 2017年8月24日(木) 00:45

King(qpwakaba) さんが書きました:
カーボンファイバー さんが書きました:33,951,744バイトがたったの147,200バイトになり、つまり25000%削減されました!

どこから25,000%という値が出たかわかりませんが、計算すると0.43%のデータサイズになっているので、およそ99.6%の削減だと思うのですが。。

よく考えたら、100%以上の削減は、計算上マイナスになってしまいますね
昔の自分は、サイズ量が1/250になっていたので、25000%と深く考えずに言ってたらしいですね……
ご指摘ありがとうございます

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by King(qpwakaba) » 2017年8月23日(水) 17:27

カーボンファイバー さんが書きました:33,951,744バイトがたったの147,200バイトになり、つまり25000%削減されました!

どこから25,000%という値が出たかわかりませんが、計算すると0.43%のデータサイズになっているので、およそ99.6%の削減だと思うのですが。。

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by カーボンファイバー » 2017年8月23日(水) 15:48

自己解決しました。
ZipOutputStreamを使うことで圧縮することが肝みたいですね
33,951,744バイトがたったの147,200バイトになり、つまり99.6%削減されました!
圧縮レベルを指定することによって、書き込み速度とサイズの釣り合いを調整することができそうですね。
*間違いを指摘されたので修正済み

ブロックをバイナリファイルに保存すると、サイズがでかくなる

投稿記事 by カーボンファイバー » 2017年8月22日(火) 20:01

件名のとおりです。
保存したい領域の情報をファイルに書き込むため、以下のような方法で行っています。

1. FileOutputStreamのインスタンスを作成(実際にはBufferedOutputStreamでバッファする)
2. 保存する立方体空間のなかで、起点からの終点の距離(終点のx座標が起点のx座標より小さい場合、xの距離はマイナスになる。y, zも同様)を計算し、int型をbyte型に変換してから保存します。
3. 起点に近いブロックから、forループでブロックID、データをbyte型で保管します
この方法なら保存に必要なサイズは少ないはずなのですが、なぜかかなりのサイズをとります
Windowsのプロパティで調べたところ256x256x256ブロックで33,949,198バイトです。(256*256*256*2は33,554,432なのでサイズは理論上と近いです)
ちなみに自分のサーバーのワールドフォルダのサイズは6,862,645バイトです。256*256*256サイズの立方体がワールドの五倍もサイズを取るなんて信じられません。
なぜCraftBukkitに比べて自分のプラグインはこんなにも量をとるのかという問題の解決に向けて、回答よろしくお願いします

問題のコードはこちら
コード: 全て選択
package secret.io;

import secret.DystopiaPlugin;
import org.bukkit.Location;
import org.bukkit.block.Block;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.logging.Logger;

public class BlocksWriter {

    private final Location start;
    private final Location end;
    private final File file;


    public BlocksWriter(Location start, Location end, File file){
        this.start = start;
        this.end = end;
        this.file = file;
    }

    public void write() throws IOException{
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }

        if(!file.exists()){
            file.createNewFile();
        }

        if(start.getWorld() != end.getWorld()){
            throw new IllegalArgumentException("Worlds of the locations must be the same!");
        }

        int distanceX = end.getBlockX() - start.getBlockX();
        int distanceY = end.getBlockY() - start.getBlockY();
        int distanceZ = end.getBlockZ() - start.getBlockZ();
        Logger l =DystopiaPlugin.getInstance().getLogger();
        try(BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))){
            writeInt(out, distanceX);
            writeInt(out, distanceY);
            writeInt(out, distanceZ);
            for(int x = 0; Math.abs(x) <= Math.abs(distanceX);){
                for(int y = 0; Math.abs(y) <= Math.abs(distanceY);){
                    for(int z = 0; Math.abs(z) <= Math.abs(distanceZ);){
                        Block targetBlock = start.clone().add(x, y, z).getBlock();
                        out.write(targetBlock.getTypeId());
                        out.write(targetBlock.getData());
                        if(distanceZ > 0)
                            z++;
                        else
                            z--;
                    }
                    if(distanceY > 0)
                        y++;
                    else
                        y--;
                }

                if(distanceX > 0)
                    x++;
                else
                    x--;
            }
        }
    }

    private void writeInt(BufferedOutputStream b, int loc) throws IOException {
        b.write(ByteBuffer.allocate(4).putInt(loc).array());
    }

}

*JavaDocを付け忘れていたので各メソッドの説明
writeInt:void...intをバイト配列に変換して保存します
write():void...起点と終点を利用して、fileに書き込みます

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by TKGEX » 2017年8月07日(月) 23:28

返信遅れてすみません。
なるほど...取得タイミングがちがかったのですね。
そこに気をつけて修正したら無事表示することができました!
ありがとうございました!

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by amata1219 » 2017年8月01日(火) 08:54

TKGEX さんが書きました:受けたダメージをホログラムにして表示するプラグインを作っていたのですが
target.damage(10);
このようにしてダメージを与えて

@EventHandler
public void onTest(EntityDamageByEntityEvent event){
Entity entity = event.getEntity();
Entity damager = event.getDamager();
double damage = event.getDamage();

if(damager.hasMetadata("Test")){
event.setDamage(damage + (damage * 0.2));
}
}
ダメージを与える人が指定したMetadataを持っていたらダメージ
が20%上昇するようにしたんです
そして、targetの最後に受けたダメージを受けて表示しようしました.
double lastDamage = live.getLastDamage();
Holograms holo = new Holograms(Text, live.getLocation());
holo.show(player, plugin);
検証して見たら、
表示されたのはダメージが上昇する前(10ダメージ)のものでした
ですが、onTestでevent.getDamage()をしてみると12ダメージになっていました
これはどういうことなのでしょうか?
正しく表示するにはどうしたら良いのでしょうか
よろしくお願いします
長文失礼しました。


TKGEXさん、こんにちは。

SpigotAPIドキュメントを参照しますと、どうやらe.getLastDamage()はダメージ取得のタイミングが、ダメージを受けた直後に発生する無敵状態のタイミングの様です。e.getDamage()とは取得のタイミングが違うためそこで誤差が生じる様です。
ですので、特に理由が無ければe.getDamage()を使用する事を推奨します。

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by TKGEX » 2017年7月30日(日) 13:06

受けたダメージをホログラムにして表示するプラグインを作っていたのですが
target.damage(10);
このようにしてダメージを与えて

@EventHandler
public void onTest(EntityDamageByEntityEvent event){
Entity entity = event.getEntity();
Entity damager = event.getDamager();
double damage = event.getDamage();

if(damager.hasMetadata("Test")){
event.setDamage(damage + (damage * 0.2));
}
}
ダメージを与える人が指定したMetadataを持っていたらダメージ
が20%上昇するようにしたんです
そして、targetの最後に受けたダメージを受けて表示しようしました.
double lastDamage = live.getLastDamage();
Holograms holo = new Holograms(Text, live.getLocation());
holo.show(player, plugin);
検証して見たら、
表示されたのはダメージが上昇する前(10ダメージ)のものでした
ですが、onTestでevent.getDamage()をしてみると12ダメージになっていました
これはどういうことなのでしょうか?
正しく表示するにはどうしたら良いのでしょうか
よろしくお願いします
長文失礼しました。

Re: 【総合】トピック立てるまでもない質問【Bukkit Plugin制作】

投稿記事 by skyteamsystem » 2017年7月29日(土) 18:57

amata1219 さんが書きました:
skyteamsystem さんが書きました:こんにちは!
今、アカウントが乗っ取られていると判断した場合BANするプラグインを作っています。
その中で、初めて参加したプレイヤーのIPをファイルに保存して、2回目からの参加はその保存したIPと比較して
変更があった場合BANする動作を考えているのですが私の知識だけでは難しく調べても出てこなかったので
個々の人に相談したいと思いました。(誤動作を考えてあとで少しソースを変更します)

皆さんの知恵を使わしてください!


skyteamsystemさん、こんにちは。

まず、その仕様ですと恐らく誤処罰量産機になりかねません。
問題点を挙げさせて頂きますと、普段私達が使用しているIPアドレスは動的IPアドレスと呼ばれるもので、定期的にプロバイダ側で変わったりします。
それに、モデムやルーターの電源を入れ直すと変更される場合もあります。また、旅行先等の別端末で接続した場合も問題が発生しますよね。
その都度、何も問題の無いアカウントがBANされ、解除申請が来て管理側の負担も間違えなく増えるかと思われます。
そこで個人的な意見になりますが、アクセス拒否はBANでなくKICKを推奨します。
そして、IP変更があった際に予め対応出来るような仕様を用意すること、IP変更時の際に管理側にIP変更が起きた事を伝えられるアクセス拒否解除申請フォーラムでも用意すべきです。特にJapanMinecraftServersのアカウントシステムの様な、所有者のアカウントと紐付けされているアカウントで申請出来る環境が良いかと思われます。

IP変更が発生した場合にBANする動作と軽々しく仰られていますが、誤処罰されたユーザーの心情や状況を一度お考えになって下さい。
勿論、システムの開発は自由です。ですが、アカウント乗っ取りといった理由であれど、確定的な証拠が無い訳であり、IPの変更だけでBANされる。アカウント所有者にしてみれば、理不尽過ぎる現実ではないでしょうか。それに、ローカルBANの情報ですら出回っている世の中です。他所へ行けば不審がられる可能性も十分にある訳です。殆どの方がマルチプレイで快適な生活を楽しみたいはずです。誤処罰が一人のプレイヤーをどれだけ悲しませるのか、十分に考えた上での開発をして下さい。

返答ありがとうございます!
確かに私もこの文章を読んで利用者側の気持ちになってみました。
そこで新しく学ぶことや知ることがたくさんありました!
これからのプラグイン開発やサーバーの運営体制などを見直していきたいと思います。
本当にありがとうございました!

Re: スペクテイターモードのプレイヤーをあるプレイヤーに憑依させる方法

投稿記事 by kemottomausu » 2017年7月29日(土) 14:38

amata1219 さんが書きました:
kemottomausu さんが書きました:何度も質問すいません・・
前回の金の管理はVaultを使うことで何とかなりましたが、今度はプレイヤーが死んだときに、playerをスペクターモードにして、 killerに乗り移させる(?)方法が知りたいです。
簡単に言うとキルカメラが作りたいということです
一応、プレイヤーをスペクテイターモードにすることはできたので、その点は大丈夫です
また、一定時間経過すれば、スペクテイターは解除され、スポーンポイントに飛ばされるようになっているのでそこら辺も大丈夫です

こんな感じです↓
コード: 全て選択
public void onPlayerDeathEvent(PlayerDeathEvent event) {
      Player player = event.getEntity();
      Player killer = null;
      try {
         killer = player.getKiller();
      } catch (Exception e) {
         killer = null;
      }

               //省略(スペクテイターにする作業など)

               //ここに憑依させる命令

               //省略(タイマーif文などなど)

               //ここに憑依を解除する命令
}


海外のサイトとかで探したんですが、自分の力では見つけられませんでした。
ご回答よろしくお願いします。


kemottomausuさん、こんにちは。
憑依自体は簡単でして、setPassenger()を使用するだけで実装可能です。
下記コードの様にして頂ければ動作するはずです。
コード: 全て選択
killer.setPassenger(player);

一応、SpigotAPIドキュメントのEntity関連の説明記事貼っておきますね。
org.bukkit.entity


ご回答ありがとうございます。SpigotAPIリファレンスをもっと注意して読めばわかることでしたね・・・
すいませんでした。

ページトップ

x