diff --git a/.gitignore b/.gitignore
index 3e7ef6d..2823d02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,5 @@
/release
.idea/
*.iml
+/bin/
+dependency-reduced-pom.xml
diff --git a/.travis.yml b/.travis.yml
index 93c9606..edea56c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,9 @@
language: java
jdk:
- - oraclejdk7
- - oraclejdk8
+ - oraclejdk11
+ - openjdk8
+ - openjdk10
+ - openjdk11
branches:
only:
- master
diff --git a/lib/PermissionsEx-1.23.1.jar b/lib/PermissionsEx-1.23.1.jar
new file mode 100644
index 0000000..0e9a753
Binary files /dev/null and b/lib/PermissionsEx-1.23.1.jar differ
diff --git a/pom.xml b/pom.xml
index 7c9ae1e..7ac74a9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,135 +1,215 @@
-
- 4.0.0
- org.bitbucket.ucchy
- UndineMailer
- 2.0.0
- A mail system plugin for bukkit server
-
-
-
- GNU Lesser General Public License version 3
- http://www.gnu.org/licenses/lgpl-3.0.en.html
- repo
-
-
-
-
- UTF-8
-
-
-
-
- internal.repo
- Temporary Staging Repository
- file://${basedir}/../mvn-repo
-
-
-
-
- ${project.artifactId}
- clean javadoc:jar source:jar deploy
-
-
- src/main/resources
- true
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.5.1
-
- 1.6
- 1.6
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.10.4
-
- 1.6
- UTF-8
- UTF-8
- UTF-8
- public
- true
-
- http://docs.oracle.com/javase/6/docs/api/
- https://hub.spigotmc.org/javadocs/bukkit/
-
-
-
-
- org.apache.maven.plugins
- maven-assembly-plugin
- 2.6
-
- ${project.artifactId}-${project.version}
-
- distribution.xml
-
-
-
-
- deploy
-
- assembly
-
-
-
-
-
-
-
-
-
- spigot-repo
- Spigot Maven Repository
- https://hub.spigotmc.org/nexus/content/groups/public
-
-
- vault-repo
- Vault Repository
- http://nexus.hc.to/content/repositories/pub_releases
-
-
- pex-repo
- PermissionsEx Repository
- http://pex-repo.aoeu.xyz
-
-
-
-
-
- org.bukkit
- bukkit
- 1.10.2-R0.1-SNAPSHOT
-
-
- net.milkbowl.vault
- VaultAPI
- 1.6
- true
-
-
- ru.tehkode
- PermissionsEx
- 1.23.1
- true
-
-
- net.gravitydevelopment.updater
- updater
-
-
-
-
- junit
- junit
- 4.12
- test
-
-
-
+
+ 4.0.0
+ org.bitbucket.ucchy
+ UndineMailer
+ 2.0.0
+ A mail system plugin for bukkit server
+
+
+
+ GNU Lesser General Public License version 3
+ http://www.gnu.org/licenses/lgpl-3.0.en.html
+ repo
+
+
+
+
+ UTF-8
+
+
+
+
+ internal.repo
+ Temporary Staging Repository
+ file://${basedir}/../mvn-repo
+
+
+
+
+ ${project.artifactId}
+ clean javadoc:jar source:jar deploy
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.1.0
+
+ 1.8
+ UTF-8
+ UTF-8
+ UTF-8
+ public
+ true
+
+ https://docs.oracle.com/javase/jp/8/docs/api/
+ https://hub.spigotmc.org/javadocs/bukkit/
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.1
+
+ false
+
+
+
+ package
+
+ shade
+
+
+ false
+ true
+
+
+ com.github.ucchyocean:MessagingUtility
+ com.github.ucchyocean:ItemConfigUtility
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.1.1
+
+ ${project.artifactId}-${project.version}
+
+ distribution.xml
+
+
+
+
+ deploy
+
+
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+ 1.3.1
+
+
+
+
+
+
+ spigot-repo
+ Spigot Maven Repository
+ https://hub.spigotmc.org/nexus/content/groups/public
+
+
+ jitpack.io
+ Vault Repository
+ https://jitpack.io/
+
+
+ pex-repo
+ PermissionsEx Repository
+ http://pex-repo.aoeu.xyz
+
+
+ pcgf-repo
+ PCGF PluginLib Repository
+ https://repo.pcgamingfreaks.at/repository/everything
+
+
+ ucchy-github
+ ucchy github repository
+ https://raw.github.com/ucchyocean/mvn-repo/master
+
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.16.2-R0.1-SNAPSHOT
+ true
+ provided
+
+
+ com.github.MilkBowl
+ VaultAPI
+ 1.7
+ true
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+
+
+ ru.tehkode
+ PermissionsEx
+ 1.23.1
+ true
+ system
+ ${project.basedir}/lib/PermissionsEx-1.23.1.jar
+
+
+ net.gravitydevelopment.updater
+ updater
+
+
+
+
+ com.google.code.gson
+ gson
+
+ 2.8.0
+ provided
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.32.3
+ runtime
+
+
+ mysql
+ mysql-connector-java
+ 5.1.49
+ runtime
+
+
+ com.github.ucchyocean
+ MessagingUtility
+ 0.0.3
+ true
+
+
+ com.github.ucchyocean
+ ItemConfigUtility
+ 0.0.5
+ true
+
+
+ junit
+ junit
+ 4.13.1
+ test
+
+
+
diff --git a/src/main/java/org/bitbucket/ucchy/undine/AttachmentBoxManager.java b/src/main/java/org/bitbucket/ucchy/undine/AttachmentBoxManager.java
index a0bf6fa..e94d453 100644
--- a/src/main/java/org/bitbucket/ucchy/undine/AttachmentBoxManager.java
+++ b/src/main/java/org/bitbucket/ucchy/undine/AttachmentBoxManager.java
@@ -25,7 +25,7 @@ public class AttachmentBoxManager {
private HashMap editmodeBoxes;
private HashMap attachmentBoxes;
- private HashMap indexCache;
+ private HashMap indexCache;
/**
* コンストラクタ
@@ -35,7 +35,7 @@ public AttachmentBoxManager(UndineMailer parent) {
this.parent = parent;
editmodeBoxes = new HashMap();
attachmentBoxes = new HashMap();
- indexCache = new HashMap();
+ indexCache = new HashMap();
}
/**
@@ -43,12 +43,13 @@ public AttachmentBoxManager(UndineMailer parent) {
* @param player プレイヤー
* @param インベントリ名
*/
- private String displayEditmodeBox(Player player) {
+ private void displayEditmodeBox(Player player) {
// 既に、該当プレイヤーの編集中ボックスインベントリがある場合は、そちらを表示する
if ( editmodeBoxes.containsKey(player) ) {
player.openInventory(editmodeBoxes.get(player));
- return editmodeBoxes.get(player).getName();
+ return;
+ //return editmodeBoxes.get(player).getName();
}
// 添付ボックスの作成
@@ -71,7 +72,7 @@ private String displayEditmodeBox(Player player) {
editmodeBoxes.put(player, box);
player.openInventory(box);
- return box.getName();
+ //return box.getName();
}
/**
@@ -105,12 +106,13 @@ public void clearEditmodeBox(Player player) {
* @param mail メール
* @param インベントリ名
*/
- private String displayAttachmentBox(Player player, MailData mail) {
+ private void displayAttachmentBox(Player player, MailData mail) {
// 既に、該当メールの添付ボックスインベントリがある場合は、そちらを表示する
if ( attachmentBoxes.containsKey(mail.getIndex()) ) {
player.openInventory(attachmentBoxes.get(mail.getIndex()));
- return attachmentBoxes.get(mail.getIndex()).getName();
+ return;
+ //return attachmentBoxes.get(mail.getIndex()).getName();
}
// 添付ボックスの作成
@@ -134,7 +136,7 @@ private String displayAttachmentBox(Player player, MailData mail) {
// 指定されたplayerの画面に添付ボックスを表示する
player.openInventory(box);
- return box.getName();
+ //return box.getName();
}
/**
@@ -144,7 +146,7 @@ private String displayAttachmentBox(Player player, MailData mail) {
*/
public void displayAttachBox(Player player, MailData mail) {
- if ( mail.isEditmode() ) {
+ if ( !mail.isSent() ) {
displayEditmodeBox(player);
} else {
displayAttachmentBox(player, mail);
@@ -152,7 +154,7 @@ public void displayAttachBox(Player player, MailData mail) {
}
// メールのインデクスを記録しておく
- indexCache.put(player, mail.getIndex());
+ indexCache.put(player, mail);
}
/**
@@ -163,7 +165,7 @@ public void displayAttachBox(Player player, MailData mail) {
*/
protected boolean isOpeningAttachBox(Player player) {
return indexCache.containsKey(player)
- && indexCache.get(player) > 0;
+ && indexCache.get(player).isSent();
}
/**
@@ -174,7 +176,7 @@ protected boolean isOpeningAttachBox(Player player) {
*/
protected boolean isOpeningEditmodeBox(Player player) {
return indexCache.containsKey(player)
- && indexCache.get(player) == 0;
+ && !indexCache.get(player).isSent();
}
/**
@@ -186,19 +188,17 @@ protected void syncAttachBox(Player player) {
// 開いていたボックスのインデクスが記録されていないなら、何もしない
if ( !indexCache.containsKey(player) ) return;
+ // 同期するボックスとメールを取得する
+ MailData mail = indexCache.get(player);
+
// インデクスを削除する
- int index = indexCache.get(player);
indexCache.remove(player);
- // 同期するボックスとメールを取得する
- MailData mail;
Inventory inv;
- if ( index == 0 ) {
- mail = parent.getMailManager().getEditmodeMail(MailSender.getMailSender(player));
+ if ( !mail.isSent() ) {
inv = editmodeBoxes.get(player);
} else {
- mail = parent.getMailManager().getMail(index);
- inv = attachmentBoxes.get(index);
+ inv = attachmentBoxes.get(mail.getIndex());
}
// 一旦取り出して再度挿入することで、アイテムをスタックして整理する
@@ -227,7 +227,7 @@ protected void syncAttachBox(Player player) {
// メール詳細を開く
if ( player.isOnline() ) {
- if ( mail.isEditmode() ) {
+ if ( !mail.isSent() ) {
parent.getMailManager().displayEditmode(
MailSender.getMailSender(player));
} else {
diff --git a/src/main/java/org/bitbucket/ucchy/undine/MailData.java b/src/main/java/org/bitbucket/ucchy/undine/MailData.java
index 80eb63f..da53583 100644
--- a/src/main/java/org/bitbucket/ucchy/undine/MailData.java
+++ b/src/main/java/org/bitbucket/ucchy/undine/MailData.java
@@ -5,380 +5,41 @@
*/
package org.bitbucket.ucchy.undine;
-import java.io.File;
-import java.io.IOException;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.Objects;
import org.bitbucket.ucchy.undine.group.GroupData;
-import org.bitbucket.ucchy.undine.group.GroupManager;
import org.bitbucket.ucchy.undine.group.SpecialGroupAll;
-import org.bitbucket.ucchy.undine.item.ItemConfigParseException;
-import org.bitbucket.ucchy.undine.item.ItemConfigParser;
import org.bitbucket.ucchy.undine.sender.MailSender;
-import org.bitbucket.ucchy.undine.sender.MailSenderPlayer;
-import org.bukkit.Bukkit;
import org.bukkit.Location;
-import org.bukkit.World;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
/**
* メールのデータ
* @author ucchy
*/
-public class MailData implements Comparable, Cloneable {
+public abstract class MailData implements Comparable, Cloneable {
public static final int MESSAGE_MAX_SIZE = 15;
private static final int SUMMARY_MAX_SIZE = 45;
- // 編集中に設定される属性
- private List to;
- private List toGroups;
- private MailSender from;
- private List message;
- private List attachments;
- private double costMoney;
- private ItemStack costItem;
-
- // 送信後に設定される属性
- private int index;
- private List toTotal;
- private List readFlags;
- private List trashFlags;
- private List attachmentsOriginal;
- private boolean isAttachmentsOpened;
- private boolean isAttachmentsCancelled;
- private boolean isAttachmentsRefused;
- private String attachmentsRefusedReason;
- private Date date;
- private Location location;
-
- /**
- * コンストラクタ
- */
- public MailData() {
- this(new ArrayList(), null, new ArrayList());
- }
-
- /**
- * コンストラクタ
- * @param to 宛先
- * @param from 送り主
- * @param message メッセージ
- */
- public MailData(List to, MailSender from, String message) {
- this(to, from, new ArrayList());
- this.message.add(message);
- }
-
- /**
- * コンストラクタ
- * @param to 宛先
- * @param from 送り主
- * @param message メッセージ
- */
- public MailData(List to, MailSender from, List message) {
- this(to, from, message, new ArrayList());
- }
-
- /**
- * コンストラクタ
- * @param to 宛先
- * @param from 送り主
- * @param message メッセージ
- * @param attachments 添付アイテム
- */
- public MailData(List to, MailSender from, List message,
- List attachments) {
- this(to, from, message, attachments, 0, null);
- }
-
- /**
- * コンストラクタ
- * @param to 宛先
- * @param from 送り主
- * @param message メッセージ
- * @param attachments 添付アイテム
- * @param costMoney 受け取りにかかる金額
- * @param costItem 受け取りにかかる取引アイテム
- */
- public MailData(List to, MailSender from, List message,
- List attachments, double costMoney, ItemStack costItem) {
- this(to, from, message, attachments, costMoney, costItem, new ArrayList());
- }
-
- /**
- * コンストラクタ
- * @param to 宛先
- * @param from 送り主
- * @param message メッセージ
- * @param attachments 添付アイテム
- * @param costMoney 受け取りにかかる金額
- * @param costItem 受け取りにかかる取引アイテム
- * @param toGroup 宛先グループ
- */
- public MailData(List to, MailSender from, List message,
- List attachments, double costMoney, ItemStack costItem,
- List toGroup) {
- this.index = 0;
- this.to = to;
- this.toGroups = toGroup;
- this.from = from;
- this.message = message;
- this.attachments = attachments;
- this.costMoney = costMoney;
- this.costItem = costItem;
- this.readFlags = new ArrayList();
- this.trashFlags = new ArrayList();
- this.isAttachmentsOpened = false;
- this.isAttachmentsCancelled = false;
- this.isAttachmentsRefused = false;
- }
+ protected int index = 0;
+
+ /** メールが送信されたかどうか。Database モード用の変数であり、フラットファイルモードでは index == 0 のとき isSent == true と判定する */
+ private boolean isSent;
/**
* 指定されたファイルへ保存する
* @param file 保存先
*/
- protected void save(File file) {
-
- YamlConfiguration config = new YamlConfiguration();
- saveToConfigSection(config);
- try {
- config.save(file);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 指定されたコンフィグセクションへ保存する
- * @param section コンフィグセクション
- */
- protected void saveToConfigSection(ConfigurationSection section) {
-
- ArrayList toList = new ArrayList();
- for ( MailSender t : to ) {
- toList.add(t.toString());
- }
- section.set("to", toList);
-
- section.set("toGroups", toGroups);
-
- if ( toTotal != null ) {
- ArrayList toTotalList = new ArrayList();
- for ( MailSender t : toTotal ) {
- toTotalList.add(t.toString());
- }
- section.set("toTotal", toTotalList);
- }
-
- section.set("from", from.toString());
- section.set("message", message);
-
- if ( attachments != null ) {
- ConfigurationSection sub = section.createSection("attachments");
- int i = 1;
- for ( ItemStack item : attachments ) {
- ConfigurationSection subsub = sub.createSection("attachment" + i++);
- ItemConfigParser.setItemToSection(subsub, item);
- }
- }
-
- section.set("costMoney", costMoney);
-
- if ( costItem != null ) {
- ConfigurationSection sub = section.createSection("costItem");
- ItemConfigParser.setItemToSection(sub, costItem);
- }
-
- section.set("index", index);
-
- ArrayList flagList = new ArrayList();
- for ( MailSender t : readFlags ) {
- flagList.add(t.toString());
- }
- section.set("readFlags", flagList);
-
- ArrayList trashList = new ArrayList();
- for ( MailSender t : trashFlags ) {
- trashList.add(t.toString());
- }
- section.set("trashFlags", trashList);
-
- if ( attachmentsOriginal != null ) {
- ConfigurationSection sub = section.createSection("attachmentsOriginal");
- int i = 1;
- for ( ItemStack item : attachmentsOriginal ) {
- ConfigurationSection subsub = sub.createSection("attachment" + i++);
- ItemConfigParser.setItemToSection(subsub, item);
- }
- }
-
- if ( date != null ) {
- section.set("date", date.getTime());
- }
-
- if ( location != null ) {
- ConfigurationSection locSec = section.createSection("location");
- locSec.set("world", location.getWorld().getName());
- locSec.set("x", location.getX());
- locSec.set("y", location.getY());
- locSec.set("z", location.getZ());
- locSec.set("yaw", location.getYaw());
- locSec.set("pitch", location.getPitch());
- }
-
- section.set("isAttachmentsCancelled", isAttachmentsCancelled);
- section.set("isAttachmentsRefused", isAttachmentsRefused);
- section.set("attachmentsRefusedReason", attachmentsRefusedReason);
- }
-
- /**
- * 指定されたファイルからロードする
- * @param file ファイル
- * @return ロードされたMailData
- */
- protected static MailData load(File file) {
- YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
- return loadFromConfigSection(config);
- }
-
- /**
- * 指定されたコンフィグセクションからロードする
- * @param section コンフィグセクション
- * @return ロードされたMailData
- */
- protected static MailData loadFromConfigSection(ConfigurationSection section) {
-
- MailData data = new MailData();
-
- data.to = new ArrayList();
- for ( String t : section.getStringList("to") ) {
- MailSender sender = MailSender.getMailSenderFromString(t);
- if ( sender != null ) {
- data.to.add(sender);
- }
- }
-
- data.toGroups = section.getStringList("toGroups");
-
- if ( section.contains("toTotal") ) {
- data.toTotal = new ArrayList();
- for ( String t : section.getStringList("toTotal") ) {
- MailSender sender = MailSender.getMailSenderFromString(t);
- if ( sender != null ) {
- data.toTotal.add(sender);
- }
- }
- }
-
- data.from = MailSender.getMailSenderFromString(section.getString("from"));
- data.message = section.getStringList("message");
-
- if ( section.contains("attachments") ) {
- data.attachments = new ArrayList();
-
- for ( String name : section.getConfigurationSection("attachments").getKeys(false) ) {
- ConfigurationSection sub = section.getConfigurationSection("attachments." + name);
- try {
- ItemStack item = ItemConfigParser.getItemFromSection(sub);
- data.attachments.add(item);
- } catch (ItemConfigParseException e) {
- e.printStackTrace();
- }
- }
- }
-
- data.costMoney = section.getInt("costMoney", 0);
- if ( section.contains("costItem") ) {
- try {
- data.costItem = ItemConfigParser.getItemFromSection(
- section.getConfigurationSection("costItem"));
- } catch (ItemConfigParseException e) {
- e.printStackTrace();
- }
- }
-
- data.index = section.getInt("index");
-
- data.readFlags = new ArrayList();
- for ( String t : section.getStringList("readFlags") ) {
- MailSender sender = MailSender.getMailSenderFromString(t);
- if ( sender != null ) {
- data.readFlags.add(sender);
- }
- }
-
- data.trashFlags = new ArrayList();
- for ( String t : section.getStringList("trashFlags") ) {
- MailSender sender = MailSender.getMailSenderFromString(t);
- if ( sender != null ) {
- data.trashFlags.add(sender);
- }
- }
-
- if ( section.contains("attachmentsOriginal") ) {
- data.attachmentsOriginal = new ArrayList();
-
- for ( String name :
- section.getConfigurationSection("attachmentsOriginal").getKeys(false) ) {
- ConfigurationSection sub =
- section.getConfigurationSection("attachmentsOriginal." + name);
- try {
- ItemStack item = ItemConfigParser.getItemFromSection(sub);
- data.attachmentsOriginal.add(item);
- } catch (ItemConfigParseException e) {
- e.printStackTrace();
- }
- }
- }
-
- if ( section.contains("date") ) {
- data.date = new Date(section.getLong("date"));
- }
-
- if ( section.contains("location") && section.contains("location.world") ) {
- ConfigurationSection locSec = section.getConfigurationSection("location");
- World world = Bukkit.getWorld(locSec.getString("world"));
- if ( world != null ) {
- double x = locSec.getDouble("x");
- double y = locSec.getDouble("y");
- double z = locSec.getDouble("z");
- double yaw = locSec.getDouble("yaw");
- double pitch = locSec.getDouble("pitch");
- data.location = new Location(world, x, y, z, (float)yaw, (float)pitch);
- }
- }
-
- data.isAttachmentsCancelled = section.getBoolean("isAttachmentsCancelled", false);
- data.isAttachmentsRefused = section.getBoolean("isAttachmentsRefused", false);
- data.attachmentsRefusedReason = section.getString("attachmentsRefusedReason");
-
- return data;
- }
-
- /**
- * このオブジェクトの複製を作成して返す。
- * @see java.lang.Object#clone()
- */
- public MailData clone() {
- return new MailData(
- new ArrayList(to), from, message,
- new ArrayList(attachments), costMoney, costItem,
- toGroups);
- }
+ public abstract void save();
/**
* 設定されている宛先を全て消去する
*/
- public void deleteAllTo() {
- to.clear();
- toGroups.clear();
- }
+ public abstract void deleteAllTo();
/**
* このメールのインデクス番号を取得します。
@@ -392,7 +53,7 @@ public int getIndex() {
* このメールのインデクス番号を設定します(メール送信時に自動で割り当てられます)。
* @param index インデクス番号
*/
- protected void setIndex(int index) {
+ public void setIndex(int index) {
this.index = index;
}
@@ -400,133 +61,88 @@ protected void setIndex(int index) {
* このメールの宛先を取得します。
* @return 宛先
*/
- public List getTo() {
- return to;
- }
+ public abstract List getTo();
/**
* このメールの宛先を設定します。
* @param line 宛先番号(0から始まることに注意)
* @param to 宛先
*/
- public void setTo(int line, MailSender to) {
- if ( this.to.size() <= line ) {
- this.to.add(to);
- } else if ( this.to.size() > line ) {
- this.to.set(line, to);
- }
+ public abstract void setTo(int line, MailSender to);
- // 全体メールだった場合は、全体グループを除去しておく。
- if ( isAllMail() ) {
- toGroups.remove(SpecialGroupAll.NAME);
- }
- }
+ /**
+ * このメールの宛先を追加します。
+ * @param to 宛先
+ */
+ public abstract void addTo(MailSender to);
/**
* このメールの宛先を追加します。
* @param to 宛先
*/
- public void addTo(MailSender to) {
- setTo(Integer.MAX_VALUE, to);
- }
+ public abstract void addTo(List to);
/**
* このメールの指定された宛先を削除します。
* @param line 宛先番号(0から始まることに注意)
*/
- public void deleteTo(int line) {
- if ( this.to.size() > line ) {
- this.to.remove(line);
- }
- }
+ public abstract void deleteTo(int line);
/**
* このメールの発信元を取得します。
* @return 発信元
*/
- public MailSender getFrom() {
- return from;
- }
+ public abstract MailSender getFrom();
/**
* このメールの発信元を設定します。
* @param from 発信元
*/
- public void setFrom(MailSender from) {
- this.from = from;
- }
+ public abstract void setFrom(MailSender from);
/**
* このメールのメッセージを取得します。
* @return メッセージ
*/
- public List getMessage() {
- return message;
- }
+ public abstract List getMessage();
/**
* このメールのメッセージを設定します。
* @param message メッセージ
*/
- public void setMessage(List message) {
- this.message = message;
- }
+ public abstract void setMessage(List message);
/**
* このメールのメッセージを設定します。
* @param line 行番号(0から始まることに注意)
* @param message メッセージ
*/
- public void setMessage(int line, String message) {
- while ( this.message.size() <= line ) {
- this.message.add("");
- }
- this.message.set(line, message);
- }
+ public abstract void setMessage(int line, String message);
/**
* このメールのメッセージに、指定した内容を追加します。
* @param message メッセージ
*/
- public void addMessage(String message) {
- String[] lines = message.split("\n");
- for ( String line : lines ) {
- this.message.add(line);
- }
- }
+ public abstract void addMessage(String message);
/**
* このメールのメッセージの、指定された行番号を削除します。
* @param line 宛先番号(0から始まることに注意)
*/
- public void deleteMessage(int line) {
- if ( this.message.size() > line && line >= 0 ) {
- this.message.remove(line);
- }
- }
+ public abstract void deleteMessage(int line);
/**
* 宛先グループを取得します。
* @return 宛先グループ
*/
- public List getToGroups() {
- return toGroups;
- }
+ public abstract List getToGroups();
/**
* 宛先グループを取得します。
* @return 宛先グループ
*/
public List getToGroupsConv() {
- GroupManager manager = UndineMailer.getInstance().getGroupManager();
- List result = new ArrayList();
- for ( String name : toGroups ) {
- GroupData group = manager.getGroup(name);
- if ( group != null ) {
- result.add(group);
- }
- }
- return result;
+ return UndineMailer.getInstance().getGroupManager().getGroups(getToGroups());
}
/**
@@ -534,31 +150,11 @@ public List getToGroupsConv() {
* @param line 宛先番号(0から始まることに注意)
* @param group グループ
*/
- public void setToGroup(int line, String group) {
-
- // 追加するグループが全体グループなら、
- // 他の宛先を全て削除する
- if ( SpecialGroupAll.NAME.equals(group) ) {
- this.to.clear();
- this.toGroups.clear();
- this.toGroups.add(group);
- return;
- }
-
- if ( this.toGroups.size() <= line ) {
- this.toGroups.add(group);
- } else if ( this.toGroups.size() > line ) {
- this.toGroups.set(line, group);
- }
-
- // 全体グループが含まれていたなら、全体グループを除去する
- if ( toGroups.contains(SpecialGroupAll.NAME) ) {
- toGroups.remove(SpecialGroupAll.NAME);
- }
- }
+ public abstract void setToGroup(int line, String group);
/**
* このメールの宛先グループに、新しいグループを追加します。
+ *
* @param group グループ名
*/
public void addToGroup(String group) {
@@ -569,278 +165,208 @@ public void addToGroup(String group) {
* このメールの宛先グループの、指定された行番号を削除します。
* @param line 宛先番号(0から始まることに注意)
*/
- public void deleteToGroup(int line) {
- if ( this.toGroups.size() > line && line >= 0 ) {
- this.toGroups.remove(line);
- }
- }
+ public abstract void deleteToGroup(int line);
/**
* 統合宛先を設定する
* @param total 統合宛先
*/
- protected void setToTotal(List total) {
- this.toTotal = total;
- }
+ protected abstract void setToTotal(List total);
/**
* 統合宛先(宛先+宛先グループの和集合)を取得する。未送信メールの場合はnullになる。
* @return 統合宛先
*/
- public List getToTotal() {
- return toTotal;
- }
+ public abstract List getToTotal();
/**
* このメールに添付されたアイテムを取得します。
* @return 添付アイテム
*/
- public List getAttachments() {
- return attachments;
- }
+ public abstract List getAttachments();
/**
* このメールの添付アイテムを設定します。
* @param attachments 添付アイテム
*/
- public void setAttachments(List attachments) {
- this.attachments = attachments;
- }
+ public abstract void setAttachments(List attachments);
/**
* 指定されたアイテムを添付アイテムに追加します。
* @param item アイテム
*/
- public void addAttachment(ItemStack item) {
- this.attachments.add(item);
- }
+ public abstract void addAttachment(ItemStack item);
/**
* このメールを読んだ人のリストを取得します。
* @return 読んだ人のリスト
*/
- public List getReadFlags() {
- return readFlags;
- }
+ public abstract List getReadFlags();
/**
* このメールに削除フラグを付けた人のリストを取得します。
* @return 削除フラグをつけている人のリスト
*/
- public List getTrashFlags() {
- return trashFlags;
- }
+ public abstract List getTrashFlags();
/**
* このメールの添付アイテムを受け取るのに必要な金額を取得します。
* @return 受け取り金額
*/
- public double getCostMoney() {
- return costMoney;
- }
+ public abstract double getCostMoney();
/**
* このメールの添付アイテムを受け取るのに必要な金額を設定します。
* @param feeMoney 受け取り金額
*/
- public void setCostMoney(double feeMoney) {
- this.costMoney = feeMoney;
- }
+ public abstract void setCostMoney(double feeMoney);
/**
* このメールの添付アイテムを受け取るのに必要な引き換えアイテムを取得します。
* @return 引き換えアイテム
*/
- public ItemStack getCostItem() {
- return costItem;
- }
+ public abstract ItemStack getCostItem();
/**
* このメールの添付アイテムを受け取るのに必要な引き換えアイテムを設定します。
* @param feeItem 引き換えアイテム
*/
- public void setCostItem(ItemStack feeItem) {
- this.costItem = feeItem;
- }
+ public abstract void setCostItem(ItemStack feeItem);
/**
* このメールの送信時間を取得します。
* @return 送信時間
*/
- public Date getDate() {
- return date;
- }
+ public abstract Date getDate();
/**
* このメールの送信時間を設定します(メール送信時に自動で割り当てられます)。
* @param date 送信時間
*/
- protected void setDate(Date date) {
- this.date = date;
- }
+ protected abstract void setDate(Date date);
/**
* このメールが送信された地点を取得します。
* @return 送信地点
*/
- public Location getLocation() {
- return location;
- }
+ public abstract Location getLocation();
/**
* このメールの送信地点を設定します(メール送信時に自動で割り当てられます)。
* @param location 送信地点
*/
- public void setLocation(Location location) {
- this.location = location;
- }
+ public abstract void setLocation(Location location);
/**
* メール送信時の添付アイテムを取得します。
* @return メール送信時の添付アイテム
*/
- public List getAttachmentsOriginal() {
- return attachmentsOriginal;
- }
+ public abstract List getAttachmentsOriginal();
/**
* attachmentOriginalに、添付ファイルのコピーを行います
* (メール送信時に自動で行われます)。
*/
- protected void makeAttachmentsOriginal() {
- attachmentsOriginal = new ArrayList(attachments);
- }
+ protected abstract void makeAttachmentsOriginal();
/**
* 指定したプレイヤーが、このメールを読んだかどうかを返します。
* @param player プレイヤー
* @return 読んだかどうか
*/
- public boolean isRead(MailSender player) {
- return readFlags.contains(player);
- }
+ public abstract boolean isRead(MailSender player);
/**
* 指定した名前のsenderの既読マークを付ける
* @param sender sender
*/
- public void setReadFlag(MailSender sender) {
- if ( !readFlags.contains(sender) ) {
- readFlags.add(sender);
- }
- }
+ public abstract void setReadFlag(MailSender sender);
/**
* 指定した人が、このメールに削除マークをつけているかどうかを返します。
* @param sender
* @return 削除マークをつけているかどうか
*/
- public boolean isSetTrash(MailSender sender) {
- return trashFlags.contains(sender);
- }
+ public abstract boolean isSetTrash(MailSender sender);
/**
* 指定した人の削除マークを付ける
* @param sender
*/
- public void setTrashFlag(MailSender sender) {
- if ( !trashFlags.contains(sender) ) {
- trashFlags.add(sender);
- }
- }
+ public abstract void setTrashFlag(MailSender sender);
/**
* 指定した人の削除マークを消す
* @param sender
*/
- public void removeTrashFlag(MailSender sender) {
- if ( trashFlags.contains(sender) ) {
- trashFlags.remove(sender);
- }
- }
+ public abstract void removeTrashFlag(MailSender sender);
/**
* 指定された名前のプレイヤーは、このメールの関係者かどうかを返す。
* @param sender sender
* @return 指定された名前がtoまたはfromに含まれるかどうか
*/
- public boolean isRelatedWith(MailSender sender) {
- if ( isAllMail() ) return true;
- if ( from.equals(sender) ) return true;
- if ( toTotal != null ) return toTotal.contains(sender);
- return to.contains(sender);
- }
+ public abstract boolean isRelatedWith(MailSender sender);
/**
* 指定された名前のプレイヤーは、このメールの受信者かどうかを返す。
* @param sender sender
* @return 指定された名前がtoに含まれるかどうか
*/
- public boolean isRecipient(MailSender sender) {
- if ( isAllMail() ) return true;
- if ( toTotal != null ) return toTotal.contains(sender);
- return to.contains(sender);
- }
+ public abstract boolean isRecipient(MailSender sender);
/**
* このメールは編集中モードなのかどうかを返す
* @return 編集中かどうか
*/
- public boolean isEditmode() {
- return (index == 0);
+ public boolean isSent() {
+ return isSent;
+ }
+
+ /**
+ * このメールを送信済みとしてマークする。
+ */
+ public void setSent() {
+ this.isSent = true;
}
/**
* このメールの添付アイテムがオープンされたのかどうかを返す
* @return 添付アイテムがオープンされたのかどうか
*/
- public boolean isAttachmentsOpened() {
- return isAttachmentsOpened;
- }
+ public abstract boolean isAttachmentsOpened();
/**
* このメールの添付アイテムをオープンされたとして記録する。
* 受信者が添付ボックスを一度でも開いた事がある状態なら、
* 送信者は添付アイテムをキャンセルすることができなくなる。
*/
- public void setOpenAttachments() {
- this.isAttachmentsOpened = true;
- }
+ public abstract void setOpenAttachments();
/**
* このメールの添付アイテムがキャンセルされたのかどうかを返す
* @return 添付アイテムがキャンセルされたのかどうか
*/
- public boolean isAttachmentsCancelled() {
- return isAttachmentsCancelled;
- }
+ public abstract boolean isAttachmentsCancelled();
/**
* このメールの添付アイテムをキャンセルする。
* 添付アイテムがキャンセルされると、受信者はボックスを開けなくなり、
* 逆に送信者がボックスを開くことができるようになる。
*/
- public void cancelAttachments() {
- this.isAttachmentsCancelled = true;
- this.costItem = null;
- this.costMoney = 0;
- }
+ public abstract void cancelAttachments();
/**
* このメールの添付アイテムが拒否されたのかどうかを返す
* @return 添付アイテムが拒否されたのかどうか
*/
- public boolean isAttachmentsRefused() {
- return isAttachmentsRefused;
- }
+ public abstract boolean isAttachmentsRefused();
/**
* 受取拒否の理由を取得します。
* @return 受取拒否の理由(設定されていない場合はnullになることに注意すること)
*/
- public String getAttachmentsRefusedReason() {
- return attachmentsRefusedReason;
- }
+ public abstract String getAttachmentsRefusedReason();
/**
* このメールの添付アイテムを拒否する。
@@ -848,23 +374,23 @@ public String getAttachmentsRefusedReason() {
* 逆に送信者がボックスを開くことができるようになる。
* @param attachmentsRefusedReason 拒否理由
*/
- public void refuseAttachments(String attachmentsRefusedReason) {
- this.isAttachmentsCancelled = true; // キャンセルフラグも立てる
- this.isAttachmentsRefused = true;
- if ( attachmentsRefusedReason != null
- && attachmentsRefusedReason.length() > 0 ) {
- this.attachmentsRefusedReason = attachmentsRefusedReason;
- }
- this.costItem = null;
- this.costMoney = 0;
- }
+ public abstract void refuseAttachments(String attachmentsRefusedReason);
+
+
+ /**
+ * このオブジェクトの複製を作成して返す。
+ *
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public abstract MailData clone();
/**
* このメールが全体メールなのかどうかを返します。
* @return 全体メールかどうか
*/
public boolean isAllMail() {
- return toGroups.contains(SpecialGroupAll.NAME);
+ return getToGroups().contains(SpecialGroupAll.NAME);
}
/**
@@ -886,11 +412,11 @@ public int compareTo(MailData other) {
* "送信者 (送信日時) 1行目の内容"
* @return サマリー
*/
- protected String getInboxSummary() {
+ public String getInboxSummary() {
- String fdate = getFormattedDate(date);
+ String fdate = getFormattedDate(getDate());
String summary = String.format("%s (%s) %s",
- from.getName(), fdate, Utility.removeColorCode(message.get(0)));
+ getFrom().getName(), fdate, Utility.removeColorCode(getMessage().get(0)));
// 長すぎる場合は切る
if ( summary.length() > SUMMARY_MAX_SIZE + 2 ) {
@@ -905,15 +431,15 @@ protected String getInboxSummary() {
* "受信者 (送信日時) 1行目の内容"
* @return サマリー
*/
- protected String getOutboxSummary() {
+ public String getOutboxSummary() {
- String fdate = getFormattedDate(date);
+ String fdate = getFormattedDate(getDate());
String todesc = joinToAndGroup();
if ( todesc.length() > 15 ) { // 長すぎる場合は切る
todesc = todesc.substring(0, 15);
}
String summary = String.format("%s (%s) %s",
- todesc, fdate, Utility.removeColorCode(message.get(0)));
+ todesc, fdate, Utility.removeColorCode(getMessage().get(0)));
// 長すぎる場合は切る
if ( summary.length() > SUMMARY_MAX_SIZE + 2 ) {
@@ -930,13 +456,13 @@ protected String getOutboxSummary() {
private String joinToAndGroup() {
StringBuffer buffer = new StringBuffer();
- for ( MailSender item : to ) {
+ for ( MailSender item : getTo() ) {
if ( buffer.length() > 0 ) {
buffer.append(", ");
}
buffer.append(item.getName());
}
- for ( String group : toGroups ) {
+ for ( String group : getToGroups() ) {
if ( buffer.length() > 0 ) {
buffer.append(", ");
}
@@ -958,41 +484,21 @@ private String getFormattedDate(Date date) {
* データのアップグレードを行う。
* @return アップグレードを実行したかどうか
*/
- protected boolean upgrade() {
- boolean upgraded = false;
- for ( MailSender ms : to ) {
- if ( ms instanceof MailSenderPlayer ) {
- if ( ((MailSenderPlayer) ms).upgrade() ) {
- upgraded = true;
- }
- }
- }
- if ( from instanceof MailSenderPlayer ) {
- if ( ((MailSenderPlayer) from).upgrade() ) {
- upgraded = true;
- }
- }
- for ( MailSender ms : toTotal ) {
- if ( ms instanceof MailSenderPlayer ) {
- if ( ((MailSenderPlayer) ms).upgrade() ) {
- upgraded = true;
- }
- }
- }
- for ( MailSender ms : readFlags ) {
- if ( ms instanceof MailSenderPlayer ) {
- if ( ((MailSenderPlayer) ms).upgrade() ) {
- upgraded = true;
- }
- }
- }
- for ( MailSender ms : trashFlags ) {
- if ( ms instanceof MailSenderPlayer ) {
- if ( ((MailSenderPlayer) ms).upgrade() ) {
- upgraded = true;
- }
- }
+ protected abstract boolean upgrade();
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof MailDataFlatFile)) {
+ return false;
}
- return upgraded;
+ MailDataFlatFile mailDataDatabase = (MailDataFlatFile) o;
+ return index == mailDataDatabase.index;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(index);
}
}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/MailDataFlatFile.java b/src/main/java/org/bitbucket/ucchy/undine/MailDataFlatFile.java
new file mode 100644
index 0000000..7e16f35
--- /dev/null
+++ b/src/main/java/org/bitbucket/ucchy/undine/MailDataFlatFile.java
@@ -0,0 +1,978 @@
+/*
+ * @author ucchy
+ * @license LGPLv3
+ * @copyright Copyright ucchy 2015
+ */
+package org.bitbucket.ucchy.undine;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.bitbucket.ucchy.undine.group.SpecialGroupAll;
+import org.bitbucket.ucchy.undine.sender.MailSender;
+import org.bitbucket.ucchy.undine.sender.MailSenderPlayer;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.inventory.ItemStack;
+
+import com.github.ucchyocean.itemconfig.ItemConfigParseException;
+import com.github.ucchyocean.itemconfig.ItemConfigParser;
+
+/**
+ * メールのデータ
+ * @author ucchy
+ */
+public class MailDataFlatFile extends MailData {
+
+ // 編集中に設定される属性
+ private List to;
+ private List toGroups;
+ private MailSender from;
+ private List message;
+ private List attachments;
+ private double costMoney;
+ private ItemStack costItem;
+
+ // 送信後に設定される属性
+ private List toTotal;
+ private List readFlags;
+ private List trashFlags;
+ private List attachmentsOriginal;
+ private boolean isAttachmentsOpened;
+ private boolean isAttachmentsCancelled;
+ private boolean isAttachmentsRefused;
+ private String attachmentsRefusedReason;
+ private Date date;
+ private Location location;
+
+ /**
+ * コンストラクタ
+ */
+ public MailDataFlatFile() {
+ this(new ArrayList(), null, new ArrayList());
+ }
+
+ /**
+ * コンストラクタ
+ *
+ * @param to 宛先
+ * @param from 送り主
+ * @param message メッセージ
+ */
+ public MailDataFlatFile(List to, MailSender from, String message) {
+ this(to, from, new ArrayList());
+ this.message.add(message);
+ }
+
+ /**
+ * コンストラクタ
+ *
+ * @param to 宛先
+ * @param from 送り主
+ * @param message メッセージ
+ */
+ public MailDataFlatFile(List to, MailSender from, List message) {
+ this(to, from, message, new ArrayList());
+ }
+
+ /**
+ * コンストラクタ
+ *
+ * @param to 宛先
+ * @param from 送り主
+ * @param message メッセージ
+ * @param attachments 添付アイテム
+ */
+ public MailDataFlatFile(List to, MailSender from, List message, List attachments) {
+ this(to, from, message, attachments, 0, null);
+ }
+
+ /**
+ * コンストラクタ
+ *
+ * @param to 宛先
+ * @param from 送り主
+ * @param message メッセージ
+ * @param attachments 添付アイテム
+ * @param costMoney 受け取りにかかる金額
+ * @param costItem 受け取りにかかる取引アイテム
+ */
+ public MailDataFlatFile(List to, MailSender from, List message, List attachments,
+ double costMoney, ItemStack costItem) {
+ this(to, from, message, attachments, costMoney, costItem, new ArrayList());
+ }
+
+ /**
+ * コンストラクタ
+ *
+ * @param to 宛先
+ * @param from 送り主
+ * @param message メッセージ
+ * @param attachments 添付アイテム
+ * @param costMoney 受け取りにかかる金額
+ * @param costItem 受け取りにかかる取引アイテム
+ * @param toGroup 宛先グループ
+ */
+ public MailDataFlatFile(List to, MailSender from, List message, List attachments,
+ double costMoney, ItemStack costItem, List toGroup) {
+ this.to = to;
+ this.toGroups = toGroup;
+ this.from = from;
+ this.message = message;
+ this.attachments = attachments;
+ this.costMoney = costMoney;
+ this.costItem = costItem;
+ this.readFlags = new ArrayList();
+ this.trashFlags = new ArrayList();
+ this.isAttachmentsOpened = false;
+ this.isAttachmentsCancelled = false;
+ this.isAttachmentsRefused = false;
+ }
+
+ /**
+ * このメールが送信されたかどうか、すなわち編集中かどうかを返す。
+ * @return このメールが送信されたかどうか
+ */
+ @Override
+ public boolean isSent() {
+ return index != 0;
+ }
+
+ /**
+ * ファイルへ保存する
+ */
+ @Override
+ public void save() {
+ // 編集中で未送信のメールは保存できません。
+ if (!isSent()) {
+ return;
+ }
+ String filename = String.format("%1$08d.yml", index);
+ File folder = UndineMailer.getInstance().getMailFolder();
+ File file = new File(folder, filename);
+ YamlConfiguration config = new YamlConfiguration();
+ saveToConfigSection(config);
+ try {
+ config.save(file);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 指定されたコンフィグセクションへ保存する
+ *
+ * @param section コンフィグセクション
+ */
+ protected void saveToConfigSection(ConfigurationSection section) {
+
+ ArrayList toList = new ArrayList();
+ for (MailSender t : to) {
+ toList.add(t.toString());
+ }
+ section.set("to", toList);
+
+ section.set("toGroups", toGroups);
+
+ if (toTotal != null) {
+ ArrayList toTotalList = new ArrayList();
+ for (MailSender t : toTotal) {
+ toTotalList.add(t.toString());
+ }
+ section.set("toTotal", toTotalList);
+ }
+
+ section.set("from", from.toString());
+ section.set("message", message);
+
+ if (attachments != null) {
+ ConfigurationSection sub = section.createSection("attachments");
+ int i = 1;
+ for (ItemStack item : attachments) {
+ ConfigurationSection subsub = sub.createSection("attachment" + i++);
+ ItemConfigParser.setItemToSection(subsub, item);
+ }
+ }
+
+ section.set("costMoney", costMoney);
+
+ if (costItem != null) {
+ ConfigurationSection sub = section.createSection("costItem");
+ ItemConfigParser.setItemToSection(sub, costItem);
+ }
+
+ section.set("index", index);
+
+ ArrayList flagList = new ArrayList();
+ for (MailSender t : readFlags) {
+ flagList.add(t.toString());
+ }
+ section.set("readFlags", flagList);
+
+ ArrayList trashList = new ArrayList();
+ for (MailSender t : trashFlags) {
+ trashList.add(t.toString());
+ }
+ section.set("trashFlags", trashList);
+
+ if (attachmentsOriginal != null) {
+ ConfigurationSection sub = section.createSection("attachmentsOriginal");
+ int i = 1;
+ for (ItemStack item : attachmentsOriginal) {
+ ConfigurationSection subsub = sub.createSection("attachment" + i++);
+ ItemConfigParser.setItemToSection(subsub, item);
+ }
+ }
+
+ if (date != null) {
+ section.set("date", date.getTime());
+ }
+
+ if (location != null) {
+ World world = location.getWorld();
+ if (world != null) {
+ ConfigurationSection locSec = section.createSection("location");
+ locSec.set("world", world.getName());
+ locSec.set("x", location.getX());
+ locSec.set("y", location.getY());
+ locSec.set("z", location.getZ());
+ locSec.set("yaw", location.getYaw());
+ locSec.set("pitch", location.getPitch());
+ }
+ }
+
+ section.set("isAttachmentsCancelled", isAttachmentsCancelled);
+ section.set("isAttachmentsRefused", isAttachmentsRefused);
+ section.set("attachmentsRefusedReason", attachmentsRefusedReason);
+ }
+
+ /**
+ * 指定されたファイルからロードする
+ *
+ * @param file ファイル
+ * @return ロードされたMailData
+ */
+ protected static MailDataFlatFile load(File file) {
+ YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
+ return loadFromConfigSection(config);
+ }
+
+ /**
+ * 指定されたコンフィグセクションからロードする
+ *
+ * @param section コンフィグセクション
+ * @return ロードされたMailData
+ */
+ protected static MailDataFlatFile loadFromConfigSection(ConfigurationSection section) {
+
+ MailDataFlatFile data = new MailDataFlatFile();
+
+ data.to = new ArrayList();
+ for (String t : section.getStringList("to")) {
+ MailSender sender = MailSender.getMailSenderFromString(t);
+ if (sender != null) {
+ data.to.add(sender);
+ }
+ }
+
+ data.toGroups = section.getStringList("toGroups");
+
+ if (section.contains("toTotal")) {
+ data.toTotal = new ArrayList();
+ for (String t : section.getStringList("toTotal")) {
+ MailSender sender = MailSender.getMailSenderFromString(t);
+ if (sender != null) {
+ data.toTotal.add(sender);
+ }
+ }
+ }
+
+ data.from = MailSender.getMailSenderFromString(section.getString("from"));
+ data.message = section.getStringList("message");
+
+ ConfigurationSection attachmentsSec = section.getConfigurationSection("attachments");
+ if (attachmentsSec != null) {
+ data.attachments = new ArrayList();
+
+ for (String name : attachmentsSec.getKeys(false)) {
+ ConfigurationSection sub = section.getConfigurationSection("attachments." + name);
+ try {
+ ItemStack item = ItemConfigParser.getItemFromSection(sub);
+ if (item != null)
+ data.attachments.add(item);
+ } catch (ItemConfigParseException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ data.costMoney = section.getInt("costMoney", 0);
+ if (section.contains("costItem")) {
+ try {
+ data.costItem = ItemConfigParser.getItemFromSection(section.getConfigurationSection("costItem"));
+ } catch (ItemConfigParseException e) {
+ e.printStackTrace();
+ }
+ }
+
+ data.index = section.getInt("index");
+
+ data.readFlags = new ArrayList();
+ for (String t : section.getStringList("readFlags")) {
+ MailSender sender = MailSender.getMailSenderFromString(t);
+ if (sender != null) {
+ data.readFlags.add(sender);
+ }
+ }
+
+ data.trashFlags = new ArrayList();
+ for (String t : section.getStringList("trashFlags")) {
+ MailSender sender = MailSender.getMailSenderFromString(t);
+ if (sender != null) {
+ data.trashFlags.add(sender);
+ }
+ }
+
+ ConfigurationSection attachmentsOrgSec = section.getConfigurationSection("attachmentsOriginal");
+ if (attachmentsOrgSec != null) {
+ data.attachmentsOriginal = new ArrayList();
+
+ for (String name : attachmentsOrgSec.getKeys(false)) {
+ ConfigurationSection sub = attachmentsOrgSec.getConfigurationSection(name);
+ if (sub != null) {
+ try {
+ ItemStack item = ItemConfigParser.getItemFromSection(sub);
+ data.attachmentsOriginal.add(item);
+ } catch (ItemConfigParseException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ if (section.contains("date")) {
+ data.date = new Date(section.getLong("date"));
+ }
+
+ ConfigurationSection locSec = section.getConfigurationSection("location");
+ if (locSec != null) {
+ String worldName = locSec.getString("world");
+ if (worldName != null) {
+ World world = Bukkit.getWorld(worldName);
+ if (world != null) {
+ double x = locSec.getDouble("x");
+ double y = locSec.getDouble("y");
+ double z = locSec.getDouble("z");
+ double yaw = locSec.getDouble("yaw");
+ double pitch = locSec.getDouble("pitch");
+ data.location = new Location(world, x, y, z, (float) yaw, (float) pitch);
+ }
+ }
+ }
+
+ data.isAttachmentsCancelled = section.getBoolean("isAttachmentsCancelled", false);
+ data.isAttachmentsRefused = section.getBoolean("isAttachmentsRefused", false);
+ data.attachmentsRefusedReason = section.getString("attachmentsRefusedReason");
+
+ return data;
+ }
+
+ /**
+ * このオブジェクトの複製を作成して返す。
+ *
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public MailDataFlatFile clone() {
+ return new MailDataFlatFile(new ArrayList(to), from, message, new ArrayList(attachments),
+ costMoney, costItem, toGroups);
+ }
+
+ /**
+ * 設定されている宛先を全て消去する
+ */
+ @Override
+ public void deleteAllTo() {
+ to.clear();
+ toGroups.clear();
+ }
+
+ /**
+ * このメールの宛先を取得します。
+ *
+ * @return 宛先
+ */
+ @Override
+ public List getTo() {
+ return to;
+ }
+
+ /**
+ * このメールの宛先を設定します。
+ *
+ * @param line 宛先番号(0から始まることに注意)
+ * @param to 宛先
+ */
+ @Override
+ public void setTo(int line, MailSender to) {
+ if (this.to.size() <= line) {
+ this.to.add(to);
+ } else if (this.to.size() > line) {
+ this.to.set(line, to);
+ }
+
+ // 全体メールだった場合は、全体グループを除去しておく。
+ if (isAllMail()) {
+ toGroups.remove(SpecialGroupAll.NAME);
+ }
+ }
+
+ /**
+ * このメールの宛先を追加します。
+ *
+ * @param to 宛先
+ */
+ @Override
+ public void addTo(MailSender to) {
+ setTo(Integer.MAX_VALUE, to);
+ }
+
+ /**
+ * このメールの宛后を複数追加します。
+ */
+ @Override
+ public void addTo(List to) {
+ getTo().addAll(to);
+ }
+
+ /**
+ * このメールの指定された宛先を削除します。
+ *
+ * @param line 宛先番号(0から始まることに注意)
+ */
+ @Override
+ public void deleteTo(int line) {
+ if (this.to.size() > line) {
+ this.to.remove(line);
+ }
+ }
+
+ /**
+ * このメールの発信元を取得します。
+ *
+ * @return 発信元
+ */
+ @Override
+ public MailSender getFrom() {
+ return from;
+ }
+
+ /**
+ * このメールの発信元を設定します。
+ *
+ * @param from 発信元
+ */
+ @Override
+ public void setFrom(MailSender from) {
+ this.from = from;
+ }
+
+ /**
+ * このメールのメッセージを取得します。
+ *
+ * @return メッセージ
+ */
+ @Override
+ public List getMessage() {
+ return message;
+ }
+
+ /**
+ * このメールのメッセージを設定します。
+ *
+ * @param message メッセージ
+ */
+ @Override
+ public void setMessage(List message) {
+ this.message = message;
+ }
+
+ /**
+ * このメールのメッセージを設定します。
+ *
+ * @param line 行番号(0から始まることに注意)
+ * @param message メッセージ
+ */
+ @Override
+ public void setMessage(int line, String message) {
+ while (this.message.size() <= line) {
+ this.message.add("");
+ }
+ this.message.set(line, message);
+ }
+
+ /**
+ * このメールのメッセージに、指定した内容を追加します。
+ *
+ * @param message メッセージ
+ */
+ @Override
+ public void addMessage(String message) {
+ String[] lines = message.split("\r\n|\r|\n", -1);
+ for (String line : lines) {
+ this.message.add(line);
+ }
+ }
+
+ /**
+ * このメールのメッセージの、指定された行番号を削除します。
+ *
+ * @param line 宛先番号(0から始まることに注意)
+ */
+ @Override
+ public void deleteMessage(int line) {
+ if (this.message.size() > line && line >= 0) {
+ this.message.remove(line);
+ }
+ }
+
+ /**
+ * 宛先グループを取得します。
+ *
+ * @return 宛先グループ
+ */
+ @Override
+ public List getToGroups() {
+ return toGroups;
+ }
+
+ /**
+ * このメールの宛先グループを設定します。
+ *
+ * @param line 宛先番号(0から始まることに注意)
+ * @param group グループ
+ */
+ @Override
+ public void setToGroup(int line, String group) {
+
+ // 追加するグループが全体グループなら、
+ // 他の宛先を全て削除する
+ if (SpecialGroupAll.NAME.equals(group)) {
+ this.to.clear();
+ this.toGroups.clear();
+ this.toGroups.add(group);
+ return;
+ }
+
+ if (this.toGroups.size() <= line) {
+ this.toGroups.add(group);
+ } else if (this.toGroups.size() > line) {
+ this.toGroups.set(line, group);
+ }
+
+ // 全体グループが含まれていたなら、全体グループを除去する
+ if (toGroups.contains(SpecialGroupAll.NAME)) {
+ toGroups.remove(SpecialGroupAll.NAME);
+ }
+ }
+
+ /**
+ * このメールの宛先グループの、指定された行番号を削除します。
+ *
+ * @param line 宛先番号(0から始まることに注意)
+ */
+ @Override
+ public void deleteToGroup(int line) {
+ if (this.toGroups.size() > line && line >= 0) {
+ this.toGroups.remove(line);
+ }
+ }
+
+ /**
+ * 統合宛先を設定する
+ *
+ * @param total 統合宛先
+ */
+ @Override
+ protected void setToTotal(List total) {
+ this.toTotal = total;
+ }
+
+ /**
+ * 統合宛先(宛先+宛先グループの和集合)を取得する。未送信メールの場合はnullになる。
+ *
+ * @return 統合宛先
+ */
+ @Override
+ public List getToTotal() {
+ return toTotal;
+ }
+
+ /**
+ * このメールに添付されたアイテムを取得します。
+ *
+ * @return 添付アイテム
+ */
+ @Override
+ public List getAttachments() {
+ return attachments;
+ }
+
+ /**
+ * このメールの添付アイテムを設定します。
+ *
+ * @param attachments 添付アイテム
+ */
+ @Override
+ public void setAttachments(List attachments) {
+ this.attachments = attachments;
+ }
+
+ /**
+ * 指定されたアイテムを添付アイテムに追加します。
+ *
+ * @param item アイテム
+ */
+ @Override
+ public void addAttachment(ItemStack item) {
+ this.attachments.add(item);
+ }
+
+ /**
+ * このメールを読んだ人のリストを取得します。
+ *
+ * @return 読んだ人のリスト
+ */
+ @Override
+ public List getReadFlags() {
+ return readFlags;
+ }
+
+ /**
+ * このメールに削除フラグを付けた人のリストを取得します。
+ *
+ * @return 削除フラグをつけている人のリスト
+ */
+ @Override
+ public List getTrashFlags() {
+ return trashFlags;
+ }
+
+ /**
+ * このメールの添付アイテムを受け取るのに必要な金額を取得します。
+ *
+ * @return 受け取り金額
+ */
+ @Override
+ public double getCostMoney() {
+ return costMoney;
+ }
+
+ /**
+ * このメールの添付アイテムを受け取るのに必要な金額を設定します。
+ *
+ * @param feeMoney 受け取り金額
+ */
+ @Override
+ public void setCostMoney(double feeMoney) {
+ this.costMoney = feeMoney;
+ }
+
+ /**
+ * このメールの添付アイテムを受け取るのに必要な引き換えアイテムを取得します。
+ *
+ * @return 引き換えアイテム
+ */
+ @Override
+ public ItemStack getCostItem() {
+ return costItem;
+ }
+
+ /**
+ * このメールの添付アイテムを受け取るのに必要な引き換えアイテムを設定します。
+ *
+ * @param feeItem 引き換えアイテム
+ */
+ @Override
+ public void setCostItem(ItemStack feeItem) {
+ this.costItem = feeItem;
+ }
+
+ /**
+ * このメールの送信時間を取得します。
+ *
+ * @return 送信時間
+ */
+ @Override
+ public Date getDate() {
+ return date;
+ }
+
+ /**
+ * このメールの送信時間を設定します(メール送信時に自動で割り当てられます)。
+ *
+ * @param date 送信時間
+ */
+ @Override
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ /**
+ * このメールが送信された地点を取得します。
+ *
+ * @return 送信地点
+ */
+ @Override
+ public Location getLocation() {
+ return location;
+ }
+
+ /**
+ * このメールの送信地点を設定します(メール送信時に自動で割り当てられます)。
+ *
+ * @param location 送信地点
+ */
+ @Override
+ public void setLocation(Location location) {
+ this.location = location;
+ }
+
+ /**
+ * メール送信時の添付アイテムを取得します。
+ *
+ * @return メール送信時の添付アイテム
+ */
+ @Override
+ public List getAttachmentsOriginal() {
+ return attachmentsOriginal;
+ }
+
+ /**
+ * attachmentOriginalに、添付ファイルのコピーを行います (メール送信時に自動で行われます)。
+ */
+ @Override
+ protected void makeAttachmentsOriginal() {
+ attachmentsOriginal = new ArrayList(attachments);
+ }
+
+ /**
+ * 指定したプレイヤーが、このメールを読んだかどうかを返します。
+ *
+ * @param player プレイヤー
+ * @return 読んだかどうか
+ */
+ @Override
+ public boolean isRead(MailSender player) {
+ return readFlags.contains(player);
+ }
+
+ /**
+ * 指定した名前のsenderの既読マークを付ける
+ *
+ * @param sender sender
+ */
+ @Override
+ public void setReadFlag(MailSender sender) {
+ if (!readFlags.contains(sender)) {
+ readFlags.add(sender);
+ }
+ }
+
+ /**
+ * 指定した人が、このメールに削除マークをつけているかどうかを返します。
+ *
+ * @param sender
+ * @return 削除マークをつけているかどうか
+ */
+ @Override
+ public boolean isSetTrash(MailSender sender) {
+ return trashFlags.contains(sender);
+ }
+
+ /**
+ * 指定した人の削除マークを付ける
+ *
+ * @param sender
+ */
+ @Override
+ public void setTrashFlag(MailSender sender) {
+ if (!trashFlags.contains(sender)) {
+ trashFlags.add(sender);
+ }
+ }
+
+ /**
+ * 指定した人の削除マークを消す
+ *
+ * @param sender
+ */
+ @Override
+ public void removeTrashFlag(MailSender sender) {
+ if (trashFlags.contains(sender)) {
+ trashFlags.remove(sender);
+ }
+ }
+
+ /**
+ * 指定された名前のプレイヤーは、このメールの関係者かどうかを返す。
+ *
+ * @param sender sender
+ * @return 指定された名前がtoまたはfromに含まれるかどうか
+ */
+ @Override
+ public boolean isRelatedWith(MailSender sender) {
+ if (isAllMail())
+ return true;
+ if (from.equals(sender))
+ return true;
+ if (toTotal != null)
+ return toTotal.contains(sender);
+ return to.contains(sender);
+ }
+
+ /**
+ * 指定された名前のプレイヤーは、このメールの受信者かどうかを返す。
+ *
+ * @param sender sender
+ * @return 指定された名前がtoに含まれるかどうか
+ */
+ @Override
+ public boolean isRecipient(MailSender sender) {
+ if (isAllMail())
+ return true;
+ if (toTotal != null)
+ return toTotal.contains(sender);
+ return to.contains(sender);
+ }
+
+ /**
+ * このメールの添付アイテムがオープンされたのかどうかを返す
+ *
+ * @return 添付アイテムがオープンされたのかどうか
+ */
+ @Override
+ public boolean isAttachmentsOpened() {
+ return isAttachmentsOpened;
+ }
+
+ /**
+ * このメールの添付アイテムをオープンされたとして記録する。 受信者が添付ボックスを一度でも開いた事がある状態なら、
+ * 送信者は添付アイテムをキャンセルすることができなくなる。
+ */
+ @Override
+ public void setOpenAttachments() {
+ this.isAttachmentsOpened = true;
+ }
+
+ /**
+ * このメールの添付アイテムがキャンセルされたのかどうかを返す
+ *
+ * @return 添付アイテムがキャンセルされたのかどうか
+ */
+ @Override
+ public boolean isAttachmentsCancelled() {
+ return isAttachmentsCancelled;
+ }
+
+ /**
+ * このメールの添付アイテムをキャンセルする。 添付アイテムがキャンセルされると、受信者はボックスを開けなくなり、
+ * 逆に送信者がボックスを開くことができるようになる。
+ */
+ @Override
+ public void cancelAttachments() {
+ this.isAttachmentsCancelled = true;
+ this.costItem = null;
+ this.costMoney = 0;
+ }
+
+ /**
+ * このメールの添付アイテムが拒否されたのかどうかを返す
+ *
+ * @return 添付アイテムが拒否されたのかどうか
+ */
+ @Override
+ public boolean isAttachmentsRefused() {
+ return isAttachmentsRefused;
+ }
+
+ /**
+ * 受取拒否の理由を取得します。
+ *
+ * @return 受取拒否の理由(設定されていない場合はnullになることに注意すること)
+ */
+ @Override
+ public String getAttachmentsRefusedReason() {
+ return attachmentsRefusedReason;
+ }
+
+ /**
+ * このメールの添付アイテムを拒否する。 添付アイテムが拒否されると、受信者はボックスを開けなくなり、 逆に送信者がボックスを開くことができるようになる。
+ *
+ * @param attachmentsRefusedReason 拒否理由
+ */
+ @Override
+ public void refuseAttachments(String attachmentsRefusedReason) {
+ this.isAttachmentsCancelled = true; // キャンセルフラグも立てる
+ this.isAttachmentsRefused = true;
+ if (attachmentsRefusedReason != null && attachmentsRefusedReason.length() > 0) {
+ this.attachmentsRefusedReason = attachmentsRefusedReason;
+ }
+ this.costItem = null;
+ this.costMoney = 0;
+ }
+
+ /**
+ * データのアップグレードを行う。
+ * @return アップグレードを実行したかどうか
+ */
+ @Override
+ protected boolean upgrade() {
+ boolean upgraded = false;
+ for ( MailSender ms : to ) {
+ if ( ms instanceof MailSenderPlayer ) {
+ if ( ((MailSenderPlayer) ms).upgrade() ) {
+ upgraded = true;
+ }
+ }
+ }
+ if ( from instanceof MailSenderPlayer ) {
+ if ( ((MailSenderPlayer) from).upgrade() ) {
+ upgraded = true;
+ }
+ }
+ for ( MailSender ms : toTotal ) {
+ if ( ms instanceof MailSenderPlayer ) {
+ if ( ((MailSenderPlayer) ms).upgrade() ) {
+ upgraded = true;
+ }
+ }
+ }
+ for ( MailSender ms : readFlags ) {
+ if ( ms instanceof MailSenderPlayer ) {
+ if ( ((MailSenderPlayer) ms).upgrade() ) {
+ upgraded = true;
+ }
+ }
+ }
+ for ( MailSender ms : trashFlags ) {
+ if ( ms instanceof MailSenderPlayer ) {
+ if ( ((MailSenderPlayer) ms).upgrade() ) {
+ upgraded = true;
+ }
+ }
+ }
+ return upgraded;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return super.equals(o) && o instanceof MailDataFlatFile;
+ }
+}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/MailManager.java b/src/main/java/org/bitbucket/ucchy/undine/MailManager.java
index 333d82f..4bbf67f 100644
--- a/src/main/java/org/bitbucket/ucchy/undine/MailManager.java
+++ b/src/main/java/org/bitbucket/ucchy/undine/MailManager.java
@@ -1,19 +1,9 @@
-/*
- * @author ucchy
- * @license LGPLv3
- * @copyright Copyright ucchy 2015
- */
package org.bitbucket.ucchy.undine;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
import org.bitbucket.ucchy.undine.bridge.VaultEcoBridge;
@@ -25,23 +15,20 @@
import org.bitbucket.ucchy.undine.sender.MailSenderBlock;
import org.bitbucket.ucchy.undine.sender.MailSenderConsole;
import org.bitbucket.ucchy.undine.sender.MailSenderPlayer;
-import org.bitbucket.ucchy.undine.tellraw.ClickEventType;
-import org.bitbucket.ucchy.undine.tellraw.MessageComponent;
-import org.bitbucket.ucchy.undine.tellraw.MessageParts;
-import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
-import org.bukkit.scheduler.BukkitRunnable;
+
+import com.github.ucchyocean.messaging.tellraw.ClickEventType;
+import com.github.ucchyocean.messaging.tellraw.MessageComponent;
+import com.github.ucchyocean.messaging.tellraw.MessageParts;
/**
- * メールデータマネージャ
- * @author ucchy
+ * メールデータマネージャ。
+ * NOTE: Editmode mail = 送信前のメール
+ * @author LazyGon
*/
-public class MailManager {
+public abstract class MailManager {
protected static final String MAILLIST_METAKEY = "UndineMailList";
public static final String SENDTIME_METAKEY = "MailSendTime";
@@ -54,12 +41,7 @@ public class MailManager {
private static final int PAGE_SIZE = 10;
private static final int MESSAGE_ADD_SIZE = 3;
- private ArrayList mails;
- private HashMap editmodeMails;
- private int nextIndex;
- private boolean isLoaded;
-
- private UndineMailer parent;
+ protected UndineMailer parent;
/**
* コンストラクタ
@@ -74,61 +56,7 @@ public MailManager(UndineMailer parent) {
* メールデータを再読込する
* @param リロードが完了した時に、通知する先。通知が不要なら、nullでよい。
*/
- protected void reload(final CommandSender sender) {
-
- final long start = System.currentTimeMillis();
-
- new BukkitRunnable() {
- public void run() {
-
- isLoaded = false;
- mails = new ArrayList();
- nextIndex = 1;
-
- File folder = parent.getMailFolder();
- File[] files = folder.listFiles(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.endsWith(".yml");
- }
- });
-
- if ( files != null ) {
- for ( File file : files ) {
- MailData data = MailData.load(file);
- mails.add(data);
-
- if ( nextIndex <= data.getIndex() ) {
- nextIndex = data.getIndex() + 1;
- }
- }
- }
-
- UndineMailer.getInstance().getLogger().info("Async load mail data... Done. Time: "
- + (System.currentTimeMillis() - start) + "ms, Data: " + mails.size() + ".");
-
- long upgradeStart = System.currentTimeMillis();
-
- int total = 0;
- for ( MailData mail : mails ) {
- if ( mail.upgrade() ) {
- saveMail(mail);
- total++;
- }
- }
-
- if ( total > 0 ) {
- UndineMailer.getInstance().getLogger().info("Async upgrade mail data... Done. Time: "
- + (System.currentTimeMillis() - upgradeStart) + "ms, Data: " + total + ".");
- }
-
- isLoaded = true;
-
- if ( sender != null ) {
- sender.sendMessage(Messages.get("InformationReload"));
- }
- }
- }.runTaskAsynchronously(UndineMailer.getInstance());
- }
+ protected abstract void reload(final CommandSender sender);
/**
* メールデータがロード完了したかどうか。
@@ -137,25 +65,14 @@ public boolean accept(File dir, String name) {
* 注意してください。
* @return ロード完了したかどうか
*/
- public boolean isLoaded() {
- return isLoaded;
- }
+ public abstract boolean isLoaded();
/**
* 指定されたインデクスのメールを取得する
* @param index インデクス
* @return メールデータ
*/
- public MailData getMail(int index) {
-
- if ( !isLoaded ) return null;
- for ( MailData m : mails ) {
- if ( m.getIndex() == index ) {
- return m;
- }
- }
- return null;
- }
+ public abstract MailData getMail(int index);
/**
* 新しいテキストメールを送信する
@@ -169,7 +86,9 @@ public void sendNewMail(MailSender from, MailSender to, String message) {
toList.add(to);
ArrayList messageList = new ArrayList();
messageList.add(message);
- MailData mail = new MailData(toList, from, messageList);
+ MailData mail = makeEditmodeMail(from);
+ mail.addTo(to);
+ mail.setMessage(messageList);
sendNewMail(mail);
}
@@ -183,7 +102,9 @@ public void sendNewMail(MailSender from, List to, String message) {
ArrayList messageList = new ArrayList();
messageList.add(message);
- MailData mail = new MailData(to, from, messageList);
+ MailData mail = makeEditmodeMail(from);
+ mail.addTo(to);
+ mail.setMessage(messageList);
sendNewMail(mail);
}
@@ -195,7 +116,9 @@ public void sendNewMail(MailSender from, List to, String message) {
*/
public void sendNewMail(MailSender from, List to, List message) {
- MailData mail = new MailData(to, from, message);
+ MailData mail = makeEditmodeMail(from);
+ mail.addTo(to);
+ mail.setMessage(message);
sendNewMail(mail);
}
@@ -203,214 +126,42 @@ public void sendNewMail(MailSender from, List to, List messa
* 新しいメールを送信する
* @param mail メール
*/
- public void sendNewMail(MailData mail) {
-
- // メールデータの本文が1行も無いときは、ここで1行追加を行う。
- if ( mail.getMessage().size() == 0 ) {
- mail.addMessage("");
- }
-
- // ロードが完了していないうちは、メールを送信できないようにする
- if ( !isLoaded ) {
- UndineMailer.getInstance().getLogger().warning(
- "Because mailer has not yet been initialized, mailer dropped new mail.");
- UndineMailer.getInstance().getLogger().warning(mail.getInboxSummary());
- return;
- }
-
- // 統合宛先を設定する。
- ArrayList to_total = new ArrayList();
- for ( MailSender t : mail.getTo() ) {
- if ( !to_total.contains(t) ) {
- to_total.add(t);
- }
- }
- for ( GroupData group : mail.getToGroupsConv() ) {
- for ( MailSender t : group.getMembers() ) {
- if ( !to_total.contains(t) ) {
- to_total.add(t);
- }
- }
- }
- mail.setToTotal(to_total);
-
- // インデクスを設定する
- mail.setIndex(nextIndex);
- nextIndex++;
-
- // 送信時間を設定する
- mail.setDate(new Date());
-
- // 送信地点を設定する
- mail.setLocation(mail.getFrom().getLocation());
-
- // オリジナルの添付ファイルを記録する
- mail.makeAttachmentsOriginal();
-
- // 添付が無いなら、着払い設定はクリアしておく
- if ( mail.getAttachments().size() == 0 ) {
- mail.setCostMoney(0);
- mail.setCostItem(null);
- }
-
- // 着払いアイテムが設定されているなら、着払い料金はクリアしておく
- if ( mail.getCostItem() != null ) {
- mail.setCostMoney(0);
- }
-
- // 着払い料金が無効なら、着払い料金はクリアしておく
- if ( !parent.getUndineConfig().isEnableCODMoney() ) {
- mail.setCostMoney(0);
- }
-
- // 着払いアイテム無効なら、着払いアイテムはクリアしておく
- if ( !parent.getUndineConfig().isEnableCODItem() ) {
- mail.setCostItem(null);
- }
-
- // 保存する
- mails.add(mail);
- saveMail(mail);
-
- // 宛先の人がログイン中なら知らせる
- String msg = Messages.get("InformationYouGotMail",
- "%from", mail.getFrom().getName());
-
- if ( mail.isAllMail() ) {
- for ( Player player : Utility.getOnlinePlayers() ) {
- player.sendMessage(msg);
- String pre = Messages.get("ListVerticalParts");
- sendMailLine(MailSender.getMailSender(player),
- pre, ChatColor.GOLD + mail.getInboxSummary(), mail);
- }
- } else {
- for ( MailSender to : mail.getToTotal() ) {
- if ( to.isOnline() ) {
- to.sendMessage(msg);
- String pre = Messages.get("ListVerticalParts");
- sendMailLine(to, pre, ChatColor.GOLD + mail.getInboxSummary(), mail);
- }
- }
- }
-
- // 送った時刻を、メタデータに記録する
- long time = System.currentTimeMillis();
- mail.getFrom().setStringMetadata(SENDTIME_METAKEY, time + "");
- }
+ public abstract void sendNewMail(MailData mail);
/**
* 受信したメールのリストを取得する
* @param sender 取得する対象
* @return メールのリスト
*/
- public ArrayList getInboxMails(MailSender sender) {
-
- if ( !isLoaded ) {
- return null;
- }
-
- ArrayList box = new ArrayList();
- for ( MailData mail : mails ) {
- if ( mail.isAllMail()
- || (mail.getToTotal() != null && mail.getToTotal().contains(sender))
- || mail.getTo().contains(sender) ) {
- if ( !mail.isSetTrash(sender) ) {
- box.add(mail);
- }
- }
- }
- sortNewer(box);
- return box;
- }
+ public abstract ArrayList getInboxMails(MailSender sender);
/**
* 受信したメールで未読のリストを取得する
* @param sender 取得する対象
* @return メールのリスト
*/
- public ArrayList getUnreadMails(MailSender sender) {
-
- if ( !isLoaded ) {
- return null;
- }
-
- ArrayList box = new ArrayList();
- for ( MailData mail : mails ) {
- if ( mail.isAllMail()
- || (mail.getToTotal() != null && mail.getToTotal().contains(sender))
- || mail.getTo().contains(sender) ) {
- if ( !mail.isRead(sender) && !mail.isSetTrash(sender) ) {
- box.add(mail);
- }
- }
- }
- sortNewer(box);
- return box;
- }
+ public abstract ArrayList getUnreadMails(MailSender sender);
/**
* 送信したメールのリストを取得する
* @param sender 取得する対象
* @return メールのリスト
*/
- public ArrayList getOutboxMails(MailSender sender) {
-
- if ( !isLoaded ) {
- return null;
- }
-
- ArrayList box = new ArrayList();
- for ( MailData mail : mails ) {
- if ( mail.getFrom().equals(sender) && !mail.isSetTrash(sender) ) {
- box.add(mail);
- }
- }
- sortNewer(box);
- return box;
- }
+ public abstract ArrayList getOutboxMails(MailSender sender);
/**
* 関連メールのリストを取得する
* @param sender 取得する対象
* @return メールのリスト
*/
- public ArrayList getRelatedMails(MailSender sender) {
-
- if ( !isLoaded ) {
- return null;
- }
-
- ArrayList box = new ArrayList();
- for ( MailData mail : mails ) {
- if ( mail.isRelatedWith(sender) && mail.isRead(sender)
- && !mail.isSetTrash(sender) ) {
- box.add(mail);
- }
- }
- sortNewer(box);
- return box;
- }
+ public abstract ArrayList getRelatedMails(MailSender sender);
/**
* ゴミ箱フォルダのメールリストを取得する
* @param sender 取得する対象
* @return メールのリスト
*/
- public ArrayList getTrashboxMails(MailSender sender) {
-
- if ( !isLoaded ) {
- return null;
- }
-
- ArrayList box = new ArrayList();
- for ( MailData mail : mails ) {
- if ( mail.isRelatedWith(sender) && mail.isSetTrash(sender) ) {
- box.add(mail);
- }
- }
- sortNewer(box);
- return box;
- }
+ public abstract ArrayList getTrashboxMails(MailSender sender);
/**
* 指定されたメールを開いて確認する
@@ -420,7 +171,7 @@ public ArrayList getTrashboxMails(MailSender sender) {
public void displayMail(MailSender sender, MailData mail) {
// ロード中の場合は、メールを表示できません
- if ( !isLoaded ) {
+ if ( !isLoaded() ) {
return;
}
@@ -438,101 +189,38 @@ public void displayMail(MailSender sender, MailData mail) {
* 指定されたメールデータをUndineに保存する
* @param mail メールデータ
*/
- public void saveMail(MailData mail) {
-
- // 編集中で未送信のメールは保存できません。
- if ( mail.getIndex() == 0 ) {
- return;
- }
-
- String filename = String.format("%1$08d.yml", mail.getIndex());
- File folder = parent.getMailFolder();
- File file = new File(folder, filename);
- mail.save(file);
- }
+ public abstract void saveMail(MailData mail);
/**
* 指定されたインデクスのメールを削除する
* @param index インデクス
*/
- public void deleteMail(int index) {
-
- if ( isLoaded ) {
- MailData mail = getMail(index);
- if ( mail != null ) {
- mails.remove(mail);
- }
- }
-
- String filename = String.format("%1$08d.yml", index);
- File folder = parent.getMailFolder();
- File file = new File(folder, filename);
- if ( file.exists() ) {
- file.delete();
- }
- }
+ public abstract void deleteMail(int index);
/**
* 古いメールを削除する
*/
- protected void cleanup() {
-
- if ( !isLoaded ) {
- return;
- }
-
- ArrayList queue = new ArrayList();
- int period = parent.getUndineConfig().getMailStorageTermDays();
- Date now = new Date();
-
- for ( MailData mail : mails ) {
- int days = (int)((now.getTime() - mail.getDate().getTime()) / (1000*60*60*24));
- if ( days > period ) {
- queue.add(mail.getIndex());
- }
- }
-
- for ( int index : queue ) {
- deleteMail(index);
- }
- }
+ protected abstract void cleanup();
/**
* 編集中メールを作成して返す
* @param sender 取得対象のsender
* @return 編集中メール
*/
- public MailData makeEditmodeMail(MailSender sender) {
- String id = sender.toString();
- if ( editmodeMails.containsKey(id) ) {
- return editmodeMails.get(id);
- }
- MailData mail = new MailData();
- mail.setFrom(sender);
- editmodeMails.put(id, mail);
- return mail;
- }
+ public abstract MailData makeEditmodeMail(MailSender sender);
/**
* 編集中メールを取得する
* @param sender 取得対象のsender
* @return 編集中メール(編集中でないならnull)
*/
- public MailData getEditmodeMail(MailSender sender) {
- String id = sender.toString();
- if ( editmodeMails.containsKey(id) ) {
- return editmodeMails.get(id);
- }
- return null;
- }
+ public abstract MailData getEditmodeMail(MailSender sender);
/**
* 編集中メールを削除する
* @param sender 削除対象のsender
*/
- public void clearEditmodeMail(MailSender sender) {
- editmodeMails.remove(sender.toString());
- }
+ public abstract void clearEditmodeMail(MailSender sender);
/**
* 指定されたsenderに、Inboxリストを表示する。
@@ -542,7 +230,7 @@ public void clearEditmodeMail(MailSender sender) {
public void displayInboxList(MailSender sender, int page) {
// ロード中の場合は、リストを表示しないようにする
- if ( !isLoaded ) {
+ if ( !isLoaded() ) {
return;
}
@@ -593,7 +281,7 @@ public void displayInboxList(MailSender sender, int page) {
public void displayOutboxList(MailSender sender, int page) {
// ロード中の場合は、リストを表示しないようにする
- if ( !isLoaded ) {
+ if ( !isLoaded() ) {
return;
}
@@ -637,7 +325,7 @@ public void displayOutboxList(MailSender sender, int page) {
protected void displayUnreadOnJoin(MailSender sender) {
// ロード中の場合は、リストを表示しないようにする
- if ( !isLoaded ) {
+ if ( !isLoaded() ) {
return;
}
@@ -673,7 +361,7 @@ protected void displayUnreadOnJoin(MailSender sender) {
public void displayTrashboxList(MailSender sender, int page) {
// ロード中の場合は、リストを表示しないようにする
- if ( !isLoaded ) {
+ if ( !isLoaded() ) {
return;
}
@@ -713,63 +401,19 @@ public void displayTrashboxList(MailSender sender, int page) {
/**
* 編集中メールをeditmails.ymlへ保存する
*/
- protected void storeEditmodeMail() {
-
- YamlConfiguration config = new YamlConfiguration();
- for ( String name : editmodeMails.keySet() ) {
- ConfigurationSection section = config.createSection(name);
- editmodeMails.get(name).saveToConfigSection(section);
- }
-
- try {
- File file = new File(parent.getDataFolder(), "editmails.yml");
- config.save(file);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ protected abstract void storeEditmodeMail();
/**
* editmails.ymlから編集中メールを復帰する
*/
- protected void restoreEditmodeMail() {
-
- editmodeMails = new HashMap();
-
- File file = new File(parent.getDataFolder(), "editmails.yml");
- if ( !file.exists() ) return;
-
- YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
- for ( String name : config.getKeys(false) ) {
- MailData mail = MailData.loadFromConfigSection(
- config.getConfigurationSection(name));
- editmodeMails.put(name, mail);
- }
-
- // 復帰元ファイルを削除しておく
- file.delete();
- }
+ protected abstract void restoreEditmodeMail();
/**
* 指定したsenderが使用中の添付ボックスの個数を返す
* @param sender
* @return 使用中添付ボックスの個数
*/
- public int getAttachBoxUsageCount(MailSender sender) {
-
- // ロード中の場合は、Integer最大値を返す
- if ( !isLoaded ) {
- return Integer.MAX_VALUE;
- }
-
- int count = 0;
- for ( MailData mail : mails ) {
- if ( mail.getFrom().equals(sender) && mail.getAttachments().size() > 0 ) {
- count++;
- }
- }
- return count;
- }
+ public abstract int getAttachBoxUsageCount(MailSender sender);
/**
* メールの詳細情報を表示する
@@ -795,8 +439,8 @@ public void displayMailDescription(MailSender sender, MailData mail) {
sender.sendMessage("");
}
- String num = mail.isEditmode() ? Messages.get("Editmode") : mail.getIndex() + "";
- String fdate = mail.isEditmode() ? null : getFormattedDate(mail.getDate());
+ String num = !mail.isSent() ? Messages.get("Editmode") : mail.getIndex() + "";
+ String fdate = !mail.isSent() ? null : getFormattedDate(mail.getDate());
String parts = Messages.get("DetailHorizontalParts");
String pre = Messages.get("DetailVerticalParts");
@@ -831,7 +475,7 @@ public void displayMailDescription(MailSender sender, MailData mail) {
msg.addText(pre + Messages.get("MailDetailAttachmentsLine"));
msg.addText(" ");
- if ( !mail.isEditmode() ) {
+ if ( mail.isSent() ) {
if ( (!mail.isAttachmentsCancelled() && mail.isRecipient(sender))
|| (mail.isAttachmentsCancelled() && mail.getFrom().equals(sender)) ) {
@@ -860,7 +504,7 @@ public void displayMailDescription(MailSender sender, MailData mail) {
ChatColor.AQUA);
button.setClickEvent(ClickEventType.RUN_COMMAND,
COMMAND + " attach " + mail.getIndex() + " cancel");
- button.addHoverText(Messages.get("MailDetailAttachmentBoxCancelToolTip"));
+ button.setHoverText(Messages.get("MailDetailAttachmentBoxCancelToolTip"));
msg.addParts(button);
}
@@ -879,27 +523,29 @@ public void displayMailDescription(MailSender sender, MailData mail) {
}
}
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
for ( ItemStack i : mail.getAttachments() ) {
sender.sendMessage(pre + " " + ChatColor.WHITE + getItemDesc(i, true));
}
- if ( mail.getCostMoney() > 0 || mail.getCostItem() != null ) {
- String costDesc = mail.getCostMoney() + "";
+ double costMoney = mail.getCostMoney();
+ ItemStack costItem = mail.getCostItem();
+ if ( costMoney > 0 || costItem != null ) {
+ String costDesc = costMoney + "";
VaultEcoBridge eco = UndineMailer.getInstance().getVaultEco();
if ( eco != null ) {
- costDesc = eco.format(mail.getCostMoney());
+ costDesc = eco.format(costMoney);
}
msg = new MessageComponent();
- if ( mail.getCostMoney() > 0 ) {
+ if ( costMoney > 0 ) {
msg.addText(pre + Messages.get(
"MailDetailAttachCostMoneyLine", "%fee", costDesc));
} else {
msg.addText(pre + Messages.get(
"MailDetailAttachCostItemLine", "%item",
- getItemDesc(mail.getCostItem(), true)));
+ getItemDesc(costItem, true)));
}
if ( mail.getTo().contains(sender) ) {
msg.addText(" ");
@@ -909,11 +555,11 @@ public void displayMailDescription(MailSender sender, MailData mail) {
refuseButton.setClickEvent(
ClickEventType.SUGGEST_COMMAND,
UndineCommand.COMMAND + " attach " + mail.getIndex() + " refuse ");
- refuseButton.addHoverText(
+ refuseButton.setHoverText(
Messages.get("MailDetailAttachmentBoxRefuseToolTip"));
msg.addParts(refuseButton);
}
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
}
} else if ( mail.isAttachmentsCancelled() ) {
@@ -932,7 +578,7 @@ public void displayMailDescription(MailSender sender, MailData mail) {
}
}
- if ( !mail.isEditmode() && mail.getAttachmentsOriginal() != null
+ if ( mail.isSent() && mail.getAttachmentsOriginal() != null
&& mail.getAttachmentsOriginal().size() > 0 && mail.getFrom().equals(sender) ) {
// 添付アイテムオリジナルがあり、表示先が送信者なら、元の添付アイテムを表示する。
@@ -945,7 +591,7 @@ public void displayMailDescription(MailSender sender, MailData mail) {
}
if ( sender instanceof MailSenderPlayer
- && mail.isRelatedWith(sender) && !mail.isEditmode() ) {
+ && mail.isRelatedWith(sender) && mail.isSent() ) {
if ( mail.isSetTrash(sender) ) {
// ゴミ箱に入っているメールなら、Restoreボタンを表示する
@@ -959,7 +605,7 @@ public void displayMailDescription(MailSender sender, MailData mail) {
COMMAND + " trash restore " + mail.getIndex());
msg.addParts(button);
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
} else {
// 既に添付が1つもないメールなら、Deleteボタンを表示する
@@ -994,12 +640,12 @@ public void displayMailDescription(MailSender sender, MailData mail) {
msg.addParts(button);
}
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
}
}
}
- if ( !mail.isEditmode() && mail.getLocation() != null
+ if ( mail.isSent() && mail.getLocation() != null
&& sender instanceof MailSenderPlayer
&& sender.hasPermission(PERMISSION_TELEPORT) ) {
@@ -1012,7 +658,7 @@ public void displayMailDescription(MailSender sender, MailData mail) {
COMMAND + " teleport " + mail.getIndex());
msg.addParts(button);
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
}
sendMailDescriptionPager(sender, mail.getIndex());
@@ -1039,9 +685,11 @@ public void displayEditmode(MailSender sender) {
}
// メッセージが3行に満たない場合は、この時点で空行を足しておく
- while ( mail.getMessage().size() < MESSAGE_ADD_SIZE ) {
- mail.addMessage("");
+ List message = mail.getMessage();
+ while ( message.size() < MESSAGE_ADD_SIZE ) {
+ message.add("");
}
+ mail.setMessage(message);
// 空行を挿入する
int lines = UndineMailer.getInstance().getUndineConfig().getUiEmptyLines();
@@ -1055,7 +703,8 @@ public void displayEditmode(MailSender sender) {
String title = Messages.get("EditmodeTitle");
sender.sendMessage(parts + parts + " " + title + " " + parts + parts);
- for ( int i=0; i to = mail.getTo();
+ for ( int i=0; i toGroups = mail.getToGroups();
+ for ( int i=0; i MailData.MESSAGE_MAX_SIZE ) {
num = MailData.MESSAGE_MAX_SIZE;
}
@@ -1179,7 +829,7 @@ public void displayEditmode(MailSender sender) {
ClickEventType.RUN_COMMAND,
COMMAND + " message " + num);
msg.addParts(button);
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
}
boolean senderHasPermissionOfOpenAttachBox =
@@ -1187,6 +837,10 @@ public void displayEditmode(MailSender sender) {
sender.hasPermission(PERMISSION_ATTACH_SENDMAIL);
if ( config.isEnableAttachment() && senderHasPermissionOfOpenAttachBox ) {
+ List attachments = mail.getAttachments();
+ double costMoney = mail.getCostMoney();
+ ItemStack costItem = mail.getCostItem();
+
MessageComponent msg = new MessageComponent();
msg.addText(pre);
MessageParts button = new MessageParts(
@@ -1196,26 +850,26 @@ public void displayEditmode(MailSender sender) {
COMMAND + " attach");
msg.addParts(button);
msg.addText(" ");
- msg.addText(Messages.get("EditmodeAttachNum", "%num", mail.getAttachments().size()));
- sendMessageComponent(msg, sender);
+ msg.addText(Messages.get("EditmodeAttachNum", "%num", attachments.size()));
+ sender.sendMessageComponent(msg);
boolean isEnableCODMoney = (UndineMailer.getInstance().getVaultEco() != null)
&& config.isEnableCODMoney();
boolean isEnableCODItem = config.isEnableCODItem();
- if ( mail.getAttachments().size() > 0 && (isEnableCODMoney || isEnableCODItem) ) {
+ if ( attachments.size() > 0 && (isEnableCODMoney || isEnableCODItem) ) {
MessageComponent msgfee = new MessageComponent();
msgfee.addText(pre);
- if ( mail.getCostMoney() == 0 && mail.getCostItem() == null ) {
+ if ( costMoney == 0 && costItem == null ) {
if ( isEnableCODMoney ) {
MessageParts buttonFee = new MessageParts(
Messages.get("EditmodeCostMoney"), ChatColor.AQUA);
buttonFee.setClickEvent(
ClickEventType.SUGGEST_COMMAND, COMMAND + " costmoney ");
- buttonFee.addHoverText(Messages.get("EditmodeCostMoneyToolTip"));
+ buttonFee.setHoverText(Messages.get("EditmodeCostMoneyToolTip"));
msgfee.addParts(buttonFee);
}
@@ -1228,16 +882,16 @@ public void displayEditmode(MailSender sender) {
Messages.get("EditmodeCostItem"), ChatColor.AQUA);
buttonItem.setClickEvent(
ClickEventType.SUGGEST_COMMAND, COMMAND + " costitem ");
- buttonItem.addHoverText(Messages.get("EditmodeCostItemToolTip"));
+ buttonItem.setHoverText(Messages.get("EditmodeCostItemToolTip"));
msgfee.addParts(buttonItem);
}
- } else if ( mail.getCostMoney() > 0 ) {
+ } else if ( costMoney > 0 ) {
- String costDesc = mail.getCostMoney() + "";
+ String costDesc = String.valueOf(costMoney);
VaultEcoBridge eco = UndineMailer.getInstance().getVaultEco();
if ( eco != null ) {
- costDesc = eco.format(mail.getCostMoney());
+ costDesc = eco.format(costMoney);
}
MessageParts buttonDelete = new MessageParts(
@@ -1245,38 +899,38 @@ public void displayEditmode(MailSender sender) {
buttonDelete.setClickEvent(
ClickEventType.RUN_COMMAND,
COMMAND + " costmoney 0");
- buttonDelete.addHoverText(Messages.get("EditmodeCostMoneyRemoveToolTip"));
+ buttonDelete.setHoverText(Messages.get("EditmodeCostMoneyRemoveToolTip"));
msgfee.addParts(buttonDelete);
MessageParts buttonFee = new MessageParts(
Messages.get("EditmodeCostMoneyData", "%fee", costDesc),
ChatColor.AQUA);
buttonFee.setClickEvent(
ClickEventType.SUGGEST_COMMAND,
- COMMAND + " costmoney " + mail.getCostMoney());
+ COMMAND + " costmoney " + costMoney);
msgfee.addParts(buttonFee);
} else {
- String desc = getItemDesc(mail.getCostItem(), true);
+ String desc = getItemDesc(costItem, true);
MessageParts buttonDelete = new MessageParts(
Messages.get("EditmodeCostItemRemove"), ChatColor.AQUA);
buttonDelete.setClickEvent(
ClickEventType.RUN_COMMAND,
COMMAND + " costitem remove");
- buttonDelete.addHoverText(Messages.get("EditmodeCostItemRemoveToolTip"));
+ buttonDelete.setHoverText(Messages.get("EditmodeCostItemRemoveToolTip"));
msgfee.addParts(buttonDelete);
MessageParts buttonItem = new MessageParts(
Messages.get("EditmodeCostItemData", "%item", desc),
ChatColor.AQUA);
buttonItem.setClickEvent(
ClickEventType.SUGGEST_COMMAND,
- COMMAND + " costitem " + getItemDesc(mail.getCostItem(), false));
+ COMMAND + " costitem " + getItemDesc(costItem, false));
msgfee.addParts(buttonItem);
}
- sendMessageComponent(msgfee, sender);
+ sender.sendMessageComponent(msgfee);
}
}
@@ -1292,7 +946,12 @@ public void displayEditmode(MailSender sender) {
cancelButton.setClickEvent(ClickEventType.RUN_COMMAND, COMMAND + " cancel");
last.addParts(cancelButton);
last.addText(parts);
- sendMessageComponent(last, sender);
+ sender.sendMessageComponent(last);
+
+ // メッセージがすべて空行の場合は、TIPSを表示する(see issue #90)
+ if ( areMessagesEmpty(mail) ) {
+ sender.sendMessage(Messages.get("EditmodeTipsMessage"));
+ }
}
/**
@@ -1314,13 +973,13 @@ private void sendMailDescriptionPager(MailSender sender, int index) {
// リストの取得
ArrayList list;
if ( meta.equals("inbox") ) {
- list = UndineMailer.getInstance().getMailManager().getInboxMails(sender);
+ list = getInboxMails(sender);
} else if ( meta.equals("outbox") ) {
- list = UndineMailer.getInstance().getMailManager().getOutboxMails(sender);
+ list = getOutboxMails(sender);
} else if ( meta.equals("trash") ) {
- list = UndineMailer.getInstance().getMailManager().getTrashboxMails(sender);
+ list = getTrashboxMails(sender);
} else {
- list = UndineMailer.getInstance().getMailManager().getUnreadMails(sender);
+ list = getUnreadMails(sender);
}
// ページ番号の取得
@@ -1358,7 +1017,7 @@ private void sendMailDescriptionPager(MailSender sender, int index) {
MessageParts returnButton = new MessageParts(
Messages.get("Return"), ChatColor.AQUA);
returnButton.setClickEvent(ClickEventType.RUN_COMMAND, returnCommand);
- returnButton.addHoverText(Messages.get("ReturnListToolTip"));
+ returnButton.setHoverText(Messages.get("ReturnListToolTip"));
msg.addParts(returnButton);
msg.addText(" ");
@@ -1372,7 +1031,7 @@ private void sendMailDescriptionPager(MailSender sender, int index) {
firstLabel, ChatColor.AQUA);
firstButton.setClickEvent(ClickEventType.RUN_COMMAND,
COMMAND + " read " + first);
- firstButton.addHoverText(firstToolTip);
+ firstButton.setHoverText(firstToolTip);
msg.addParts(firstButton);
msg.addText(" ");
@@ -1381,7 +1040,7 @@ private void sendMailDescriptionPager(MailSender sender, int index) {
prevLabel, ChatColor.AQUA);
prevButton.setClickEvent(ClickEventType.RUN_COMMAND,
COMMAND + " read " + prev);
- prevButton.addHoverText(prevToolTip);
+ prevButton.setHoverText(prevToolTip);
msg.addParts(prevButton);
} else {
@@ -1399,7 +1058,7 @@ private void sendMailDescriptionPager(MailSender sender, int index) {
nextLabel, ChatColor.AQUA);
nextButton.setClickEvent(ClickEventType.RUN_COMMAND,
COMMAND + " read " + next);
- nextButton.addHoverText(nextToolTip);
+ nextButton.setHoverText(nextToolTip);
msg.addParts(nextButton);
msg.addText(" ");
@@ -1408,7 +1067,7 @@ private void sendMailDescriptionPager(MailSender sender, int index) {
lastLabel, ChatColor.AQUA);
lastButton.setClickEvent(ClickEventType.RUN_COMMAND,
COMMAND + " read " + last);
- lastButton.addHoverText(lastToolTip);
+ lastButton.setHoverText(lastToolTip);
msg.addParts(lastButton);
} else {
@@ -1417,7 +1076,7 @@ private void sendMailDescriptionPager(MailSender sender, int index) {
msg.addText(" " + parts);
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
}
/**
@@ -1442,6 +1101,8 @@ private int getIndexOfMailList(int index, ArrayList list) {
* @return 文字列表現
*/
private String getItemDesc(ItemStack item, boolean forDescription) {
+ if (item == null) return "null";
+ @SuppressWarnings("deprecation")
String desc = item.getDurability() == 0 ? item.getType().toString() :
item.getType().toString() + ":" + item.getDurability();
if ( item.getAmount() == 1 ) return desc;
@@ -1453,12 +1114,8 @@ private String getItemDesc(ItemStack item, boolean forDescription) {
* メールデータのリストを、新しいメール順に並び替えする
* @param list リスト
*/
- private static void sortNewer(List list) {
- Collections.sort(list, new Comparator() {
- public int compare(MailData o1, MailData o2) {
- return o2.getDate().compareTo(o1.getDate());
- }
- });
+ protected static void sortNewer(List list) {
+ Collections.sort(list, (o1, o2) -> o2.getDate().compareTo(o1.getDate()));
}
/**
@@ -1468,7 +1125,7 @@ public int compare(MailData o1, MailData o2) {
* @param summary サマリーの文字列
* @param mail メールデータ
*/
- private void sendMailLine(
+ public void sendMailLine(
MailSender sender, String pre, String summary, MailData mail) {
MessageComponent msg = new MessageComponent();
@@ -1480,14 +1137,14 @@ private void sendMailLine(
button.setClickEvent(
ClickEventType.RUN_COMMAND,
UndineCommand.COMMAND + " read " + mail.getIndex());
- button.addHoverText(Messages.get("SummaryOpenThisMailToolTip"));
+ button.setHoverText(Messages.get("SummaryOpenThisMailToolTip"));
msg.addParts(button);
msg.addText((mail.getAttachments().size() > 0) ? "*" : " ");
msg.addText(summary);
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
}
/**
@@ -1517,7 +1174,7 @@ private void sendPager(MailSender sender, String commandPre, int page, int max)
MessageParts firstButton = new MessageParts(
firstLabel, ChatColor.AQUA);
firstButton.setClickEvent(ClickEventType.RUN_COMMAND, commandPre + " 1");
- firstButton.addHoverText(firstToolTip);
+ firstButton.setHoverText(firstToolTip);
msg.addParts(firstButton);
msg.addText(" ");
@@ -1525,7 +1182,7 @@ private void sendPager(MailSender sender, String commandPre, int page, int max)
MessageParts prevButton = new MessageParts(
prevLabel, ChatColor.AQUA);
prevButton.setClickEvent(ClickEventType.RUN_COMMAND, commandPre + " " + (page - 1));
- prevButton.addHoverText(prevToolTip);
+ prevButton.setHoverText(prevToolTip);
msg.addParts(prevButton);
} else {
@@ -1539,7 +1196,7 @@ private void sendPager(MailSender sender, String commandPre, int page, int max)
MessageParts nextButton = new MessageParts(
nextLabel, ChatColor.AQUA);
nextButton.setClickEvent(ClickEventType.RUN_COMMAND, commandPre + " " + (page + 1));
- nextButton.addHoverText(nextToolTip);
+ nextButton.setHoverText(nextToolTip);
msg.addParts(nextButton);
msg.addText(" ");
@@ -1547,7 +1204,7 @@ private void sendPager(MailSender sender, String commandPre, int page, int max)
MessageParts lastButton = new MessageParts(
lastLabel, ChatColor.AQUA);
lastButton.setClickEvent(ClickEventType.RUN_COMMAND, commandPre + " " + max);
- lastButton.addHoverText(lastToolTip);
+ lastButton.setHoverText(lastToolTip);
msg.addParts(lastButton);
} else {
@@ -1556,15 +1213,16 @@ private void sendPager(MailSender sender, String commandPre, int page, int max)
msg.addText(" " + parts);
- sendMessageComponent(msg, sender);
+ sender.sendMessageComponent(msg);
}
/**
* 言語リソース設定に従ってフォーマットされた日時の文字列を取得します。
* @param date フォーマットする日時
* @return フォーマットされた文字列
+ * TODO: privateに戻す。
*/
- private String getFormattedDate(Date date) {
+ public String getFormattedDate(Date date) {
return new SimpleDateFormat(Messages.get("DateFormat")).format(date);
}
@@ -1592,15 +1250,16 @@ private String joinToAndGroup(MailData mail) {
}
/**
- * 指定されたメッセージコンポーネントを、指定されたMailSenderに送信する。
- * @param msg メッセージコンポーネント
- * @param sender 送信先
+ * 指定されたメールのメッセージがすべて空行かどうかを判定する。
+ * @param mail メール
+ * @return すべてのメッセージが空行かどうか
*/
- private void sendMessageComponent(MessageComponent msg, MailSender sender) {
- if ( sender instanceof MailSenderPlayer && sender.isOnline() ) {
- msg.send(sender.getPlayer());
- } else if ( sender instanceof MailSenderConsole ) {
- msg.send(Bukkit.getConsoleSender());
+ private boolean areMessagesEmpty(MailData mail) {
+ for ( String line : mail.getMessage() ) {
+ if ( line != null && !line.trim().equals("") ) {
+ return false;
+ }
}
+ return true;
}
}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/MailManagerFlatFile.java b/src/main/java/org/bitbucket/ucchy/undine/MailManagerFlatFile.java
new file mode 100644
index 0000000..223f5cf
--- /dev/null
+++ b/src/main/java/org/bitbucket/ucchy/undine/MailManagerFlatFile.java
@@ -0,0 +1,529 @@
+/*
+ * @author ucchy
+ * @license LGPLv3
+ * @copyright Copyright ucchy 2015
+ */
+package org.bitbucket.ucchy.undine;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+
+import org.bitbucket.ucchy.undine.group.GroupData;
+import org.bitbucket.ucchy.undine.sender.MailSender;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+/**
+ * フラットファイルを用いたメールデータマネージャ
+ * @author ucchy
+ */
+public class MailManagerFlatFile extends MailManager {
+
+ private ArrayList mails;
+ private HashMap editmodeMails;
+ private int nextIndex;
+ private boolean isLoaded;
+
+ /**
+ * コンストラクタ
+ */
+ public MailManagerFlatFile(UndineMailer parent) {
+ super(parent);
+ }
+
+ /**
+ * メールデータを再読込する
+ *
+ * @param リロードが完了した時に、通知する先。通知が不要なら、nullでよい。
+ */
+ @Override
+ protected void reload(final CommandSender sender) {
+
+ final long start = System.currentTimeMillis();
+
+ new BukkitRunnable() {
+ public void run() {
+
+ isLoaded = false;
+ mails = new ArrayList();
+ nextIndex = 1;
+
+ File folder = parent.getMailFolder();
+ File[] files = folder.listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".yml");
+ }
+ });
+
+ if (files != null) {
+ for (File file : files) {
+ MailDataFlatFile data = MailDataFlatFile.load(file);
+ mails.add(data);
+
+ if (nextIndex <= data.getIndex()) {
+ nextIndex = data.getIndex() + 1;
+ }
+ }
+ }
+
+ UndineMailer.getInstance().getLogger().info("Async load mail data... Done. Time: "
+ + (System.currentTimeMillis() - start) + "ms, Data: " + mails.size() + ".");
+
+ long upgradeStart = System.currentTimeMillis();
+
+ int total = 0;
+ for (MailData mail : mails) {
+ if (mail.upgrade()) {
+ saveMail(mail);
+ total++;
+ }
+ }
+
+ if (total > 0) {
+ UndineMailer.getInstance().getLogger().info("Async upgrade mail data... Done. Time: "
+ + (System.currentTimeMillis() - upgradeStart) + "ms, Data: " + total + ".");
+ }
+
+ isLoaded = true;
+
+ if (sender != null) {
+ sender.sendMessage(Messages.get("InformationReload"));
+ }
+ }
+ }.runTaskAsynchronously(UndineMailer.getInstance());
+ }
+
+ /**
+ * メールデータがロード完了したかどうか。 UndineMailerは、保存されているメールデータをバックグラウンドで読み取ってロードするため、
+ * ロードが完了していないうちは、メールリストの参照、メールの送信、リロードができないので 注意してください。
+ *
+ * @return ロード完了したかどうか
+ */
+ @Override
+ public boolean isLoaded() {
+ return isLoaded;
+ }
+
+ /**
+ * 指定されたインデクスのメールを取得する
+ *
+ * @param index インデクス
+ * @return メールデータ
+ */
+ @Override
+ public MailData getMail(int index) {
+
+ if (!isLoaded)
+ return null;
+ for (MailData m : mails) {
+ if (m.getIndex() == index) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 新しいメールを送信する
+ *
+ * @param mail メール
+ */
+ @Override
+ public void sendNewMail(MailData mail) {
+ if (!(mail instanceof MailDataFlatFile)) {
+ return;
+ }
+ MailDataFlatFile fileMail = (MailDataFlatFile) mail;
+
+ // メールデータの本文が1行も無いときは、ここで1行追加を行う。
+ if (fileMail.getMessage().size() == 0) {
+ fileMail.addMessage("");
+ }
+
+ // ロードが完了していないうちは、メールを送信できないようにする
+ if (!isLoaded) {
+ UndineMailer.getInstance().getLogger()
+ .warning("Because mailer has not yet been initialized, mailer dropped new mail.");
+ UndineMailer.getInstance().getLogger().warning(fileMail.getInboxSummary());
+ return;
+ }
+
+ // 統合宛先を設定する。
+ ArrayList to_total = new ArrayList();
+ for (MailSender t : fileMail.getTo()) {
+ if (!to_total.contains(t)) {
+ to_total.add(t);
+ }
+ }
+ for (GroupData group : fileMail.getToGroupsConv()) {
+ for (MailSender t : group.getMembers()) {
+ if (!to_total.contains(t)) {
+ to_total.add(t);
+ }
+ }
+ }
+ fileMail.setToTotal(to_total);
+
+ // インデクスを設定する
+ fileMail.setIndex(nextIndex);
+ nextIndex++;
+
+ // 送信時間を設定する
+ fileMail.setDate(new Date());
+
+ // 送信地点を設定する
+ fileMail.setLocation(fileMail.getFrom().getLocation());
+
+ // オリジナルの添付ファイルを記録する
+ fileMail.makeAttachmentsOriginal();
+
+ // 添付が無いなら、着払い設定はクリアしておく
+ if (fileMail.getAttachments().size() == 0) {
+ fileMail.setCostMoney(0);
+ fileMail.setCostItem(null);
+ }
+
+ // 着払いアイテムが設定されているなら、着払い料金はクリアしておく
+ if (fileMail.getCostItem() != null) {
+ fileMail.setCostMoney(0);
+ }
+
+ // 着払い料金が無効なら、着払い料金はクリアしておく
+ if (!parent.getUndineConfig().isEnableCODMoney()) {
+ fileMail.setCostMoney(0);
+ }
+
+ // 着払いアイテム無効なら、着払いアイテムはクリアしておく
+ if (!parent.getUndineConfig().isEnableCODItem()) {
+ fileMail.setCostItem(null);
+ }
+
+ // 編集中メールだったなら編集中ではなくしておく
+ editmodeMails.values().remove(fileMail);
+
+ // 保存する
+ mails.add(fileMail);
+ saveMail(fileMail);
+
+ // 宛先の人がログイン中なら知らせる
+ String msg = Messages.get("InformationYouGotMail", "%from", fileMail.getFrom().getName());
+
+ if (fileMail.isAllMail()) {
+ for (Player player : Utility.getOnlinePlayers()) {
+ player.sendMessage(msg);
+ String pre = Messages.get("ListVerticalParts");
+ sendMailLine(MailSender.getMailSender(player), pre, ChatColor.GOLD + fileMail.getInboxSummary(), fileMail);
+ }
+ } else {
+ for (MailSender to : fileMail.getToTotal()) {
+ if (to.isOnline()) {
+ to.sendMessage(msg);
+ String pre = Messages.get("ListVerticalParts");
+ sendMailLine(to, pre, ChatColor.GOLD + fileMail.getInboxSummary(), fileMail);
+ }
+ }
+ }
+
+ // 送った時刻を、メタデータに記録する
+ long time = System.currentTimeMillis();
+ fileMail.getFrom().setStringMetadata(SENDTIME_METAKEY, time + "");
+ }
+
+ /**
+ * 受信したメールのリストを取得する
+ *
+ * @param sender 取得する対象
+ * @return メールのリスト
+ */
+ @Override
+ public ArrayList getInboxMails(MailSender sender) {
+
+ if (!isLoaded) {
+ return null;
+ }
+
+ ArrayList box = new ArrayList();
+ for (MailData mail : mails) {
+ if (mail.isAllMail() || (mail.getToTotal() != null && mail.getToTotal().contains(sender))
+ || mail.getTo().contains(sender)) {
+ if (!mail.isSetTrash(sender)) {
+ box.add(mail);
+ }
+ }
+ }
+ sortNewer(box);
+ return box;
+ }
+
+ /**
+ * 受信したメールで未読のリストを取得する
+ *
+ * @param sender 取得する対象
+ * @return メールのリスト
+ */
+ @Override
+ public ArrayList getUnreadMails(MailSender sender) {
+
+ if (!isLoaded) {
+ return null;
+ }
+
+ ArrayList box = new ArrayList();
+ for (MailData mail : mails) {
+ if (mail.isAllMail() || (mail.getToTotal() != null && mail.getToTotal().contains(sender))
+ || mail.getTo().contains(sender)) {
+ if (!mail.isRead(sender) && !mail.isSetTrash(sender)) {
+ box.add(mail);
+ }
+ }
+ }
+ sortNewer(box);
+ return box;
+ }
+
+ /**
+ * 送信したメールのリストを取得する
+ *
+ * @param sender 取得する対象
+ * @return メールのリスト
+ */
+ @Override
+ public ArrayList getOutboxMails(MailSender sender) {
+
+ if (!isLoaded) {
+ return null;
+ }
+
+ ArrayList box = new ArrayList();
+ for (MailData mail : mails) {
+ if (mail.getFrom().equals(sender) && !mail.isSetTrash(sender)) {
+ box.add(mail);
+ }
+ }
+ sortNewer(box);
+ return box;
+ }
+
+ /**
+ * 関連メールのリストを取得する
+ *
+ * @param sender 取得する対象
+ * @return メールのリスト
+ */
+ @Override
+ public ArrayList getRelatedMails(MailSender sender) {
+
+ if (!isLoaded) {
+ return null;
+ }
+
+ ArrayList box = new ArrayList();
+ for (MailData mail : mails) {
+ if (mail.isRelatedWith(sender) && mail.isRead(sender) && !mail.isSetTrash(sender)) {
+ box.add(mail);
+ }
+ }
+ sortNewer(box);
+ return box;
+ }
+
+ /**
+ * ゴミ箱フォルダのメールリストを取得する
+ *
+ * @param sender 取得する対象
+ * @return メールのリスト
+ */
+ @Override
+ public ArrayList getTrashboxMails(MailSender sender) {
+
+ if (!isLoaded) {
+ return null;
+ }
+
+ ArrayList box = new ArrayList();
+ for (MailData mail : mails) {
+ if (mail.isRelatedWith(sender) && mail.isSetTrash(sender)) {
+ box.add(mail);
+ }
+ }
+ sortNewer(box);
+ return box;
+ }
+
+ /**
+ * 指定されたメールデータをUndineに保存する
+ *
+ * @param mail メールデータ
+ */
+ @Override
+ public void saveMail(MailData mail) {
+ mail.save();
+ }
+
+ /**
+ * 指定されたインデクスのメールを削除する
+ *
+ * @param index インデクス
+ */
+ @Override
+ public void deleteMail(int index) {
+
+ if (isLoaded) {
+ MailData mail = getMail(index);
+ if (mail != null) {
+ mails.remove(mail);
+ }
+ }
+
+ String filename = String.format("%1$08d.yml", index);
+ File folder = parent.getMailFolder();
+ File file = new File(folder, filename);
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+
+ /**
+ * 古いメールを削除する
+ */
+ @Override
+ protected void cleanup() {
+
+ if (!isLoaded) {
+ return;
+ }
+
+ ArrayList queue = new ArrayList();
+ int period = parent.getUndineConfig().getMailStorageTermDays();
+ Date now = new Date();
+
+ for (MailData mail : mails) {
+ int days = (int) ((now.getTime() - mail.getDate().getTime()) / (1000 * 60 * 60 * 24));
+ if (days > period) {
+ queue.add(mail.getIndex());
+ }
+ }
+
+ for (int index : queue) {
+ deleteMail(index);
+ }
+ }
+
+ /**
+ * 編集中メールを作成して返す
+ *
+ * @param sender 取得対象のsender
+ * @return 編集中メール
+ */
+ @Override
+ public MailData makeEditmodeMail(MailSender sender) {
+ String id = sender.toString();
+ if (editmodeMails.containsKey(id)) {
+ return editmodeMails.get(id);
+ }
+ MailDataFlatFile mail = new MailDataFlatFile();
+ mail.setFrom(sender);
+ editmodeMails.put(id, mail);
+ return mail;
+ }
+
+ /**
+ * 編集中メールを取得する
+ *
+ * @param sender 取得対象のsender
+ * @return 編集中メール(編集中でないならnull)
+ */
+ @Override
+ public MailData getEditmodeMail(MailSender sender) {
+ String id = sender.toString();
+ if (editmodeMails.containsKey(id)) {
+ return editmodeMails.get(id);
+ }
+ return null;
+ }
+
+ /**
+ * 編集中メールを削除する
+ *
+ * @param sender 削除対象のsender
+ */
+ @Override
+ public void clearEditmodeMail(MailSender sender) {
+ editmodeMails.remove(sender.toString());
+ }
+
+ /**
+ * 編集中メールをeditmails.ymlへ保存する
+ */
+ @Override
+ protected void storeEditmodeMail() {
+
+ YamlConfiguration config = new YamlConfiguration();
+ for (String name : editmodeMails.keySet()) {
+ ConfigurationSection section = config.createSection(name);
+ editmodeMails.get(name).saveToConfigSection(section);
+ }
+
+ try {
+ File file = new File(parent.getDataFolder(), "editmails.yml");
+ config.save(file);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * editmails.ymlから編集中メールを復帰する
+ */
+ @Override
+ protected void restoreEditmodeMail() {
+
+ editmodeMails = new HashMap();
+
+ File file = new File(parent.getDataFolder(), "editmails.yml");
+ if (!file.exists())
+ return;
+
+ YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
+ for (String name : config.getKeys(false)) {
+ ConfigurationSection section = config.getConfigurationSection(name);
+ if (section != null) {
+ MailDataFlatFile mail = MailDataFlatFile.loadFromConfigSection(section);
+ editmodeMails.put(name, mail);
+ }
+ }
+
+ // 復帰元ファイルを削除しておく
+ file.delete();
+ }
+
+ /**
+ * 指定したsenderが使用中の添付ボックスの個数を返す
+ * @param sender
+ * @return 使用中添付ボックスの個数
+ */
+ @Override
+ public int getAttachBoxUsageCount(MailSender sender) {
+
+ // ロード中の場合は、Integer最大値を返す
+ if ( !isLoaded ) {
+ return Integer.MAX_VALUE;
+ }
+
+ int count = 0;
+ for ( MailData mail : mails ) {
+ if ( mail.getFrom().equals(sender) && mail.getAttachments().size() > 0 ) {
+ count++;
+ }
+ }
+ return count;
+ }
+}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/Messages.java b/src/main/java/org/bitbucket/ucchy/undine/Messages.java
index a42de2b..0a90d16 100644
--- a/src/main/java/org/bitbucket/ucchy/undine/Messages.java
+++ b/src/main/java/org/bitbucket/ucchy/undine/Messages.java
@@ -137,6 +137,7 @@ protected static void initialize(File _jar, File _configFolder, String lang) {
// デフォルトメッセージを、jarファイル内からロードする
defaultMessages = new YamlConfiguration();
JarFile jarFile = null;
+ BufferedReader reader = null;
try {
jarFile = new JarFile(jar);
ZipEntry zipEntry = jarFile.getEntry(String.format("messages_%s.yml", lang));
@@ -144,8 +145,7 @@ protected static void initialize(File _jar, File _configFolder, String lang) {
zipEntry = jarFile.getEntry("messages_en.yml");
}
InputStream inputStream = jarFile.getInputStream(zipEntry);
- BufferedReader reader =
- new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+ reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String line;
while ( (line = reader.readLine()) != null ) {
if ( line.startsWith("#") || !line.contains(":") ) {
@@ -160,6 +160,13 @@ protected static void initialize(File _jar, File _configFolder, String lang) {
} catch (IOException e) {
e.printStackTrace();
} finally {
+ if ( reader != null ) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // do nothing.
+ }
+ }
if ( jarFile != null ) {
try {
jarFile.close();
diff --git a/src/main/java/org/bitbucket/ucchy/undine/PlayerNameCache.java b/src/main/java/org/bitbucket/ucchy/undine/PlayerNameCache.java
deleted file mode 100644
index f20d372..0000000
--- a/src/main/java/org/bitbucket/ucchy/undine/PlayerNameCache.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * @author ucchy
- * @license LGPLv3
- * @copyright Copyright ucchy 2015
- */
-package org.bitbucket.ucchy.undine;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-
-import org.bitbucket.ucchy.undine.sender.MailSender;
-import org.bitbucket.ucchy.undine.sender.MailSenderPlayer;
-import org.bukkit.Bukkit;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.scheduler.BukkitRunnable;
-
-/**
- * プレイヤー名のキャッシュ管理クラス
- * @author ucchy
- */
-public class PlayerNameCache {
-
- private static final String FILENAME = "playercache.yml";
- private HashMap playerCache;
- private boolean isPlayerCacheLoaded;
-
- private PlayerNameCache() {
- playerCache = new HashMap();
- isPlayerCacheLoaded = false;
- }
-
- protected static PlayerNameCache load() {
-
- long start = System.currentTimeMillis();
-
- File file = new File(UndineMailer.getInstance().getDataFolder(), FILENAME);
- if ( !file.exists() ) {
- // ファイルがまだ存在しないなら、ここで空ファイルを作成する。
- YamlConfiguration temp = new YamlConfiguration();
- try {
- temp.save(file);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- PlayerNameCache cache = new PlayerNameCache();
- YamlConfiguration conf = YamlConfiguration.loadConfiguration(file);
-
- for ( String name : conf.getKeys(false) ) {
- MailSender sender = MailSender.getMailSenderFromString(conf.getString(name));
- cache.playerCache.put(name, sender);
- }
-
- UndineMailer.getInstance().getLogger().info("Load offline player data from cache... Done. Time: "
- + (System.currentTimeMillis() - start) + "ms, Data: " + cache.playerCache.size() + ".");
-
- return cache;
- }
-
- protected void save() {
-
- File file = new File(UndineMailer.getInstance().getDataFolder(), FILENAME);
-
- YamlConfiguration conf = new YamlConfiguration();
- for ( String name : playerCache.keySet() ) {
- conf.set(name, playerCache.get(name).toString());
- }
-
- try {
- conf.save(file);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- protected void refresh() {
-
- final long start = System.currentTimeMillis();
- isPlayerCacheLoaded = false;
-
- new BukkitRunnable() {
- public void run() {
- HashMap temp = new HashMap();
- for ( OfflinePlayer player : Bukkit.getOfflinePlayers() ) {
- MailSender ms = MailSenderPlayer.getMailSenderFromString(player.getName());
- if ( ms != null && ms.isValidDestination() ) {
- temp.put(player.getName(), ms);
- }
- }
- UndineMailer.getInstance().getLogger().info("Async refresh offline player data... Done. Time: "
- + (System.currentTimeMillis() - start) + "ms, Data: " + temp.size() + ".");
- playerCache = temp;
- isPlayerCacheLoaded = true;
-
- save();
- }
- }.runTaskAsynchronously(UndineMailer.getInstance());
- }
-
- protected HashMap getCache() {
- return playerCache;
- }
-
- /**
- * プレイヤーキャッシュがロードされているかどうかを返す
- * @return プレイヤーキャッシュがロードされているかどうか
- */
- protected boolean isPlayerCacheLoaded() {
- return isPlayerCacheLoaded;
- }
-}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/PlayerUuidCache.java b/src/main/java/org/bitbucket/ucchy/undine/PlayerUuidCache.java
new file mode 100644
index 0000000..fca7ebc
--- /dev/null
+++ b/src/main/java/org/bitbucket/ucchy/undine/PlayerUuidCache.java
@@ -0,0 +1,224 @@
+package org.bitbucket.ucchy.undine;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.scheduler.BukkitRunnable;
+
+/**
+ * プレイヤーのUUIDのキャッシュを管理するクラス
+ * @author ucchy
+ */
+public class PlayerUuidCache {
+
+ private HashMap caches;
+ private boolean isPlayerCacheLoaded;
+ private UUIDResolver resolver;
+
+ // コンストラクタ
+ private PlayerUuidCache() {
+ caches = new HashMap();
+ isPlayerCacheLoaded = false;
+ resolver = new UUIDResolver(
+ UndineMailer.getInstance().getUndineConfig().isUuidOnlineMode());
+ }
+
+ /**
+ * PlayerUuidCacheを、キャッシュフォルダ内のファイルからロードする。
+ * @return PlayerUuidCache
+ */
+ protected static PlayerUuidCache load() {
+
+ PlayerUuidCache puc = new PlayerUuidCache();
+ long start = System.currentTimeMillis();
+
+ File folder = UndineMailer.getInstance().getCacheFolder();
+ File[] children = folder.listFiles();
+ if ( children != null ) {
+ for ( File file : children ) {
+ if ( !file.getName().endsWith(".yml") ) {
+ continue;
+ }
+ PlayerUuidCacheData cache = PlayerUuidCacheData.load(file);
+ puc.caches.put(cache.getName(), cache);
+ }
+ }
+
+ UndineMailer.getInstance().getLogger().info("Load offline player data from cache... Done. Time: "
+ + (System.currentTimeMillis() - start) + "ms, Data: " + puc.caches.size() + ".");
+
+ return puc;
+ }
+
+ /**
+ * サーバーのプレイヤー一覧を取得し、UUIDをキャッシュする。
+ */
+ protected void refresh() {
+
+ final long start = System.currentTimeMillis();
+ isPlayerCacheLoaded = false;
+
+ new BukkitRunnable() {
+ public void run() {
+
+ // UUIDがキャッシュされているかどうか確認し、キャッシュされていないプレイヤー名をリストして、
+ // 10プレイヤーずつ、10秒ごとに、UUIDの確認と更新を行う。
+ ArrayList namesToCheck = new ArrayList<>();
+ HashMap temp = new HashMap();
+
+ for ( OfflinePlayer player : Bukkit.getOfflinePlayers() ) {
+
+ String name = player.getName();
+ if ( name == null ) continue;
+
+ if ( caches.containsKey(name) ) {
+ if ( isBefore30Days(caches.get(name).getLastKnownDate()) ) {
+ namesToCheck.add(name);
+ } else {
+ temp.put(name, caches.get(name));
+ }
+ } else {
+ namesToCheck.add(name);
+ }
+ }
+
+ int pageSize = 10; // 10 names per a request.
+ long waitTime = 1000L * 10; // 10 seconds.
+
+ for ( int index = 0; index < namesToCheck.size(); index += pageSize ) {
+ int endIndex = (index + pageSize > namesToCheck.size()) ? namesToCheck.size() : index + pageSize;
+ List next = namesToCheck.subList(index, endIndex);
+
+ Map results = resolver.getUUIDsFromNames(next);
+ for ( String name : results.keySet() ) {
+ String uuid = results.get(name);
+ PlayerUuidCacheData data = new PlayerUuidCacheData(name, uuid, new Date());
+ data.save();
+ temp.put(name, data);
+ }
+
+ if ( index + pageSize < namesToCheck.size() ) {
+ try {
+ Thread.sleep(waitTime);
+ } catch (InterruptedException e) {
+ // do nothing.
+ }
+ }
+ }
+
+ UndineMailer.getInstance().getLogger().info("Async refresh offline player data... Done. Time: "
+ + (System.currentTimeMillis() - start) + "ms, Data: " + temp.size() + ".");
+ caches = temp;
+ isPlayerCacheLoaded = true;
+ }
+ }.runTaskAsynchronously(UndineMailer.getInstance());
+ }
+
+ /**
+ * プレイヤーキャッシュがロードされているかどうかを返す
+ * @return プレイヤーキャッシュがロードされているかどうか
+ */
+ protected boolean isPlayerCacheLoaded() {
+ return isPlayerCacheLoaded;
+ }
+
+ /**
+ * キャッシュしているプレイヤー名の一覧を返す
+ * @return プレイヤー名一覧
+ */
+ protected Set getPlayerNames() {
+ return caches.keySet();
+ }
+
+ /**
+ * キャッシュされているすべてのUUIDを取得する
+ * @return すべてのUUID
+ */
+ protected HashSet getPlayerUuids() {
+ HashSet uuids = new HashSet<>();
+ for ( PlayerUuidCacheData d : caches.values() ) {
+ uuids.add(d.getUuid());
+ }
+ return uuids;
+ }
+
+ /**
+ * 指定されたプレイヤー名のUUIDをキャッシュから取得する
+ * @param name プレイヤー名
+ * @return UUID
+ */
+ protected String getUUID(String name) {
+ if ( caches.containsKey(name) ) {
+ return caches.get(name).getUuid();
+ }
+ return refreshPlayerUuid(name);
+ }
+
+ /**
+ * 指定されたUUIDのプレイヤー名をキャッシュから取得する
+ * @param uuid UUID
+ * @return プレイヤー名
+ */
+ protected String getName(String uuid) {
+ for ( PlayerUuidCacheData d : caches.values() ) {
+ if ( d.getUuid().equals(uuid) ) {
+ return d.getName();
+ }
+ }
+ return resolver.getNameFromUUID(uuid);
+ }
+
+ /**
+ * 指定されたプレイヤー名のUUIDを更新する
+ * @param name プレイヤー名
+ */
+ private String refreshPlayerUuid(String name) {
+
+ String uuid = null;
+ PlayerUuidCacheData data = null;
+ if ( caches.containsKey(name) ) {
+ data = caches.get(name);
+ if ( isBefore30Days(data.getLastKnownDate()) ) {
+ uuid = resolver.getUUIDFromName(name, new Date());
+ if ( uuid == null ) return null;
+ data = new PlayerUuidCacheData(name, uuid, new Date());
+ caches.put(name, data);
+ data.save();
+ }
+ } else {
+ uuid = resolver.getUUIDFromName(name, new Date());
+ if ( uuid == null ) return null;
+ data = new PlayerUuidCacheData(name, uuid, new Date());
+ caches.put(name, data);
+ data.save();
+ }
+
+ return uuid;
+ }
+
+ /**
+ * 指定されたプレイヤー名のUUIDを、非同期スレッドで更新する
+ * @param name プレイヤー名
+ */
+ protected void asyncRefreshPlayerUuid(String name) {
+
+ new BukkitRunnable() {
+ public void run() {
+ refreshPlayerUuid(name);
+ }
+ }.runTaskAsynchronously(UndineMailer.getInstance());
+ }
+
+ // 指定されたDateが、30日以前かどうかを判定する。
+ private static boolean isBefore30Days(Date date) {
+ return date.before(new Date(System.currentTimeMillis() - 1000L*24*3600* 30));
+ }
+}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/PlayerUuidCacheData.java b/src/main/java/org/bitbucket/ucchy/undine/PlayerUuidCacheData.java
new file mode 100644
index 0000000..a0dc7da
--- /dev/null
+++ b/src/main/java/org/bitbucket/ucchy/undine/PlayerUuidCacheData.java
@@ -0,0 +1,97 @@
+package org.bitbucket.ucchy.undine;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+
+import org.bukkit.configuration.file.YamlConfiguration;
+
+/**
+ * プレイヤーのUUIDキャッシュデータ
+ * @author ucchy
+ */
+public class PlayerUuidCacheData {
+
+ private String name;
+ private String uuid;
+ private Date lastKnownDate;
+
+ /**
+ * コンストラクタ
+ * @param name
+ * @param uuid
+ * @param lastKnownDate
+ */
+ protected PlayerUuidCacheData(String name, String uuid, Date lastKnownDate) {
+ this.name = name;
+ this.uuid = uuid;
+ this.lastKnownDate = lastKnownDate;
+ }
+
+ protected static PlayerUuidCacheData load(File file) {
+
+ YamlConfiguration conf = YamlConfiguration.loadConfiguration(file);
+ String name = conf.getString("name");
+ String uuid = conf.getString("uuid");
+ Date date = new Date(conf.getLong("lastKnownDate"));
+
+ return new PlayerUuidCacheData(name, uuid, date);
+ }
+
+ protected void save() {
+
+ File folder = UndineMailer.getInstance().getCacheFolder();
+ YamlConfiguration conf = new YamlConfiguration();
+ conf.set("name", name);
+ conf.set("uuid", uuid);
+ conf.set("lastKnownDate", lastKnownDate.getTime());
+
+ try {
+ conf.save(new File(folder, uuid + ".yml"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return uuid
+ */
+ public String getUuid() {
+ return uuid;
+ }
+
+ /**
+ * @param uuid uuid
+ */
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ /**
+ * @return lastKnownDate
+ */
+ public Date getLastKnownDate() {
+ return lastKnownDate;
+ }
+
+ /**
+ * @param lastKnownDate lastKnownDate
+ */
+ public void setLastKnownDate(Date lastKnownDate) {
+ this.lastKnownDate = lastKnownDate;
+ }
+}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/UUIDResolver.java b/src/main/java/org/bitbucket/ucchy/undine/UUIDResolver.java
new file mode 100644
index 0000000..6a45744
--- /dev/null
+++ b/src/main/java/org/bitbucket/ucchy/undine/UUIDResolver.java
@@ -0,0 +1,353 @@
+/*
+ * @author ucchy
+ * @license LGPLv3
+ * @copyright Copyright ucchy 2020
+ * This file was copied from at.pcgamingfreaks.UUIDConverter class.
+ */
+package org.bitbucket.ucchy.undine;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.TreeMap;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+
+import com.google.common.base.Charsets;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+
+/**
+ * UUIDとプレイヤー名の相互変換を行うためのクラス
+ * @author ucchy
+ */
+public class UUIDResolver {
+
+ private static final Pattern API_MAX_PROFILE_BATCH_SIZE_PATTERN = Pattern.compile(".*Not more that (?\\d+) profile name per call is allowed.*");
+ private static final String UUID_FORMAT_REGEX = "(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})";
+ private static final String UUID_FORMAT_REPLACE_TO = "$1-$2-$3-$4-$5";
+ private static final long MOJANG_QUERY_RETRY_TIME = 600000L;
+
+ private static final Gson GSON = new Gson();
+ private static final Map UUID_CACHE = new HashMap();
+
+ private boolean onlineMode = false;
+
+ /**
+ * コンストラクタ
+ */
+ public UUIDResolver() {
+ this(false);
+ }
+
+ /**
+ * コンストラクタ
+ * @param useUserCacheJson usercache.jsonからキャッシュの初期値を取得するかどうか
+ */
+ public UUIDResolver(boolean onlineMode) {
+ this.onlineMode = onlineMode;
+ if ( !onlineMode ) loadUserCache();
+ }
+
+ // usercache.jsonを、uuidCacheの初期値としてロードする
+ private void loadUserCache() {
+
+ // 既にロード済みなら何もしない
+ if ( UUID_CACHE.size() > 0 ) return;
+
+ int loaded = 0;
+ File uuidCache = new File("usercache.json");
+ if ( !uuidCache.exists() ) return;
+
+ try (JsonReader reader = new JsonReader(new FileReader(uuidCache))) {
+ CacheData[] dat = new Gson().fromJson(reader, CacheData[].class);
+ Date now = new Date();
+ for (CacheData d : dat) {
+ if (now.before(d.getExpiresDate())) {
+ loaded++;
+ UUID_CACHE.put(d.name, d.uuid);
+ }
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("Loaded " + loaded + " UUIDs from local cache.");
+ }
+
+ /**
+ * UUIDから現在のプレイヤー名を取得する
+ * @param uuid UUID
+ * @return プレイヤー名(存在しないUUIDが指定された場合はnullになる)
+ */
+ protected String getNameFromUUID(String uuid) {
+ if ( uuid == null ) return null;
+ if ( onlineMode ) {
+ NameChange[] names = getOnlineNamesFromUUID(uuid);
+ if ( names == null ) return null;
+ return names[names.length - 1].name;
+ } else {
+ // Bukkit pass-throgh mode.
+ OfflinePlayer p = Bukkit.getOfflinePlayer(UUID.fromString(uuid));
+ if ( p == null ) return null;
+ return p.getName();
+ }
+ }
+
+ /**
+ * UUIDからプレイヤー名履歴を取得する
+ * @param uuid UUID
+ * @return プレイヤー名の履歴(存在しないUUIDが指定された場合はnullになる)
+ */
+ private NameChange[] getOnlineNamesFromUUID(String uuid) {
+ NameChange[] names = null;
+ try {
+ Scanner jsonScanner = new Scanner((new URL("https://api.mojang.com/user/profiles/" + uuid.replaceAll("-", "") + "/names")).openConnection().getInputStream(), "UTF-8");
+ names = GSON.fromJson(jsonScanner.next(), NameChange[].class);
+ jsonScanner.close();
+ } catch(IOException e) {
+ if (e.getMessage().contains("HTTP response code: 429")) {
+ System.out.println("You have reached the request limit of the Mojang api! Please retry later!");
+ } else {
+ System.out.println("Looks like there is a problem with the connection with Mojang. Please retry later.");
+ }
+ } catch(Exception e) {
+ System.out.println("Looks like there is no player with this uuid!\n UUID: \"" + uuid + "\"");
+ }
+ return names;
+ }
+
+ /**
+ * プレイヤー名からUUIDを取得する。
+ * 例えば、name=ucchy、lastKnownDate=2020/04/28を指定した場合は、2020/04/28の時点でucchyというプレイヤー名を使っていた人のUUIDを取得する。
+ * @param name プレイヤー名
+ * @param lastKnownDate 時点
+ * @return UUID
+ */
+ protected String getUUIDFromName(String name, Date lastKnownDate) {
+ if ( name == null ) return null;
+ if ( onlineMode ) {
+ String uuid = getOnlineUUID(name, lastKnownDate);
+ if (uuid == null) return null;
+ if (!uuid.contains("-")) {
+ uuid = uuid.replaceAll(UUID_FORMAT_REGEX, UUID_FORMAT_REPLACE_TO);
+ }
+ return uuid;
+ } else {
+ // Bukkit pass-throgh mode.
+ @SuppressWarnings("deprecation")
+ OfflinePlayer p = Bukkit.getOfflinePlayer(name);
+ if ( p == null ) return null;
+ return p.getUniqueId().toString();
+ }
+ }
+
+ // ネットワーク経由でUUIDを取得する
+ private String getOnlineUUID(String name, Date at) {
+ if ((at == null || at.after(new Date(System.currentTimeMillis() - 1000L*24*3600* 30))) && UUID_CACHE.containsKey(name)) {
+ return UUID_CACHE.get(name);
+ }
+
+ String uuid = null;
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(
+ new URL("https://api.mojang.com/users/profiles/minecraft/" + name + ((at != null) ? "?at=" + (at.getTime()/1000L) : "")).openStream(), StandardCharsets.UTF_8))) {
+ uuid = (((JsonObject) new JsonParser().parse(in)).get("id")).getAsString();
+ if (uuid != null && (at == null || at.after(new Date(System.currentTimeMillis() - 1000L*24*3600* 30)))) {
+ UUID_CACHE.put(name, uuid);
+ }
+ } catch(MalformedURLException e) {
+ System.out.println("Failed to get uuid cause of a malformed url!\n Name: \"" + name + "\" Date: " + ((at != null) ? "?at=" + at.getTime()/1000L : "null"));
+ } catch(IOException e) {
+ if (e.getMessage().contains("HTTP response code: 429")) {
+ System.out.println("You have reached the request limit of the mojang api! Please retry later!");
+ } else {
+ System.out.println("Looks like there is a problem with the connection with mojang. Please retry later.");
+ }
+ } catch(Exception e) {
+ if(at == null) {
+ // We can't resolve the uuid for the player
+ System.out.println("Unable to get UUID for: " + name + "!");
+ } else if(at.getTime() == 0) {
+ // If it's not his first name maybe it's his current name
+ System.out.println("Unable to get UUID for: " + name + " at 0! Trying without date!");
+ uuid = getOnlineUUID(name, null);
+ } else {
+ // If we cant get the player with the date he was here last time it's likely that it is his first name
+ System.out.println("Unable to get UUID for: " + name + " at " + at.getTime()/1000L + "! Trying at=0!");
+ uuid = getOnlineUUID(name, new Date(0));
+ }
+ }
+ return uuid;
+ }
+
+ private static int BATCH_SIZE = 10; // Limit from Mojang
+
+ /**
+ * 複数のプレイヤー名からUUIDをまとめて取得する
+ * @param names プレイヤー名
+ * @return UUID
+ */
+ protected Map getUUIDsFromNames(Collection names) {
+ Map result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ for (Map.Entry entry : getUUIDsFromNamesAsUUIDs(names).entrySet()) {
+ result.put(entry.getKey(), entry.getValue().toString());
+ }
+ return result;
+ }
+
+ /**
+ * 複数のプレイヤー名からUUIDをまとめて取得する
+ * @param names プレイヤー名
+ * @return UUID
+ */
+ protected Map getUUIDsFromNamesAsUUIDs(Collection names) {
+
+ Map result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+ if ( !onlineMode ) {
+ // Bukkit pass-throgh mode.
+ for ( String name : names ) {
+ @SuppressWarnings("deprecation")
+ OfflinePlayer p = Bukkit.getOfflinePlayer(name);
+ if ( p == null ) continue;
+ result.put(name, p.getUniqueId());
+ }
+ return result;
+ }
+
+ List batch = new ArrayList<>(BATCH_SIZE);
+ Iterator players = names.iterator();
+ boolean success;
+ int fromCache = 0, fromWeb = 0;
+ while (players.hasNext()) {
+ while (players.hasNext() && batch.size() < BATCH_SIZE) {
+ String name = players.next();
+ if (UUID_CACHE.containsKey(name)) {
+ result.put(name, UUID.fromString(UUID_CACHE.get(name).replaceAll(UUID_FORMAT_REGEX, UUID_FORMAT_REPLACE_TO)));
+ fromCache++;
+ } else {
+ batch.add(name);
+ }
+ }
+
+ do {
+ HttpURLConnection connection = null;
+ try {
+ connection = (HttpURLConnection) new URL("https://api.mojang.com/profiles/minecraft").openConnection();
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/json; encoding=UTF-8");
+ connection.setUseCaches(false);
+ connection.setDoInput(true);
+ connection.setDoOutput(true);
+ try (OutputStream out = connection.getOutputStream()) {
+ out.write(GSON.toJson(batch).getBytes(Charsets.UTF_8));
+ }
+ Profile[] profiles;
+ try (Reader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
+ profiles = GSON.fromJson(in, Profile[].class);
+ }
+ for (Profile profile : profiles) {
+ result.put(profile.name, profile.getUUID());
+ UUID_CACHE.put(profile.name, profile.getUUID().toString());
+ fromWeb++;
+ }
+ } catch(IOException e) {
+ try {
+ if(connection != null) {
+ if(connection.getResponseCode() == 429) {
+ System.out.println("Reached the request limit of the mojang api!\nConverting will be paused for 10 minutes and then continue!");
+ Thread.sleep(MOJANG_QUERY_RETRY_TIME);
+ success = false;
+ continue;
+ } else {
+ InputStream errorStream = connection.getErrorStream();
+ StringBuilder errorBuilder = new StringBuilder();
+ int c;
+ while ((c = errorStream.read()) != -1) {
+ errorBuilder.append((char) c);
+ }
+ String errorMessage = errorBuilder.toString();
+ System.out.println("Mojang responded with status code: " + connection.getResponseCode() + " Message: " + errorMessage);
+ Matcher matcher = API_MAX_PROFILE_BATCH_SIZE_PATTERN.matcher(errorMessage);
+ if (connection.getResponseCode() == 400 && matcher.matches()) {
+ BATCH_SIZE = Integer.parseInt(matcher.group("batchSize"));
+ System.out.println("Reducing batch size to " + BATCH_SIZE + " and try again ...");
+ return getUUIDsFromNamesAsUUIDs(names);
+ } else {
+ e.printStackTrace();
+ }
+ }
+ } else {
+ e.printStackTrace();
+ }
+ }
+ catch(InterruptedException | IOException ignore) {}
+
+ System.out.println("Could not convert all names to uuids because of an issue. Please check the log.");
+ return result;
+ }
+ batch.clear();
+ success = true;
+ } while(!success);
+ }
+
+ System.out.println("Converted " + (fromCache + fromWeb) + "/" + names.size() + " UUIDs (" + fromCache + " of them from the cache and " + fromWeb + " from Mojang).");
+ return result;
+ }
+
+ public class NameChange {
+ public String name;
+ public long changedToAt;
+
+ public Date getChangeDate() {
+ return new Date(changedToAt);
+ }
+ }
+
+ private class Profile {
+ public String id;
+ public String name;
+
+ public UUID getUUID() {
+ return UUID.fromString(id.replaceAll(UUID_FORMAT_REGEX, UUID_FORMAT_REPLACE_TO));
+ }
+ }
+
+ private static class CacheData {
+ public String name, uuid, expiresOn;
+
+ public Date getExpiresDate() {
+ try {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(expiresOn);
+ } catch(ParseException e) {
+ e.printStackTrace();
+ }
+ return new Date(); // When we failed to parse the date we return the current time stamp
+ }
+ }
+}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/UndineConfig.java b/src/main/java/org/bitbucket/ucchy/undine/UndineConfig.java
index 34e58be..8855cb7 100644
--- a/src/main/java/org/bitbucket/ucchy/undine/UndineConfig.java
+++ b/src/main/java/org/bitbucket/ucchy/undine/UndineConfig.java
@@ -10,14 +10,15 @@
import java.util.ArrayList;
import java.util.List;
+import org.bitbucket.ucchy.undine.database.Database.DatabaseType;
import org.bitbucket.ucchy.undine.group.GroupPermissionMode;
-import org.bitbucket.ucchy.undine.item.ItemConfigParseException;
-import org.bitbucket.ucchy.undine.item.ItemConfigParser;
-import org.bitbucket.ucchy.undine.item.TradableMaterial;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemStack;
+import com.github.ucchyocean.itemconfig.ItemConfigParseException;
+import com.github.ucchyocean.itemconfig.ItemConfigParser;
+
/**
* Undineコンフィグ管理クラス
* @author ucchy
@@ -27,6 +28,24 @@ public class UndineConfig {
/** メッセージ言語 */
private String lang;
+ /** データベースの種類。 */
+ private DatabaseType databaseType;
+
+ /** MySQLでログインするためのユーザー */
+ private String mysqlUser;
+
+ /** MySQLでログインするためのパスワード */
+ private String mysqlPass;
+
+ /** MySQLでログインするためのホスト */
+ private String mysqlHost;
+
+ /** MySQLでログインするためのポート */
+ private int mysqlPort;
+
+ /** MySQLで使うデータベースの名前 */
+ private String mysqlDBName;
+
/** メールにアイテムの添付を可能にするかどうか */
private boolean enableAttachment;
@@ -55,7 +74,7 @@ public class UndineConfig {
private List disableWorldsToOpenAttachBox;
/** 添付ボックスに添付できないようにするアイテム */
- private List prohibitItemsToAttach;
+ private List prohibitItemsToAttach;
/** 着払い料金を使用するかどうか */
private boolean enableCODMoney;
@@ -129,6 +148,9 @@ public class UndineConfig {
/** ウェルカムメールの添付アイテム */
private List welcomeMailAttachments;
+ /** UUIDのオンラインモード */
+ private boolean uuidOnlineMode;
+
private UndineMailer parent;
/**
@@ -175,6 +197,12 @@ protected void reloadConfig() {
// 読み込み
lang = conf.getString("lang", "ja");
+ databaseType = DatabaseType.getByName(conf.getString("databaseType", "sqlite"));
+ mysqlUser = conf.getString("mysqlUser", "root");
+ mysqlPass = conf.getString("mysqlPass", "password");
+ mysqlHost = conf.getString("mysqlHost", "127.0.0.1");
+ mysqlPort = conf.getInt("mysqlPort", 3306);
+ mysqlDBName = conf.getString("mysqlDBName", "undinemailer");
enableAttachment = conf.getBoolean("enableAttachment", true);
enableSendFee = conf.getBoolean("enableSendFee", false);
sendFee = conf.getDouble("sendFee", 10);
@@ -225,13 +253,9 @@ protected void reloadConfig() {
welcomeMailAttachments = getItemStackListFromConfig(
conf.getConfigurationSection("welcomeMailAttachments"));
- prohibitItemsToAttach = new ArrayList();
- for ( String name : conf.getStringList("prohibitItemsToAttach") ) {
- TradableMaterial material = TradableMaterial.getMaterial(name);
- if ( material != null ) {
- prohibitItemsToAttach.add(material);
- }
- }
+ prohibitItemsToAttach = conf.getStringList("prohibitItemsToAttach");
+
+ uuidOnlineMode = conf.getBoolean("uuidOnlineMode", false);
// sendFeeは、マイナスが指定されていたら0に変更する
if ( sendFee < 0 ) {
@@ -311,6 +335,48 @@ public String getLang() {
return lang;
}
+ /**
+ * @return databaseType
+ */
+ public DatabaseType getDatabaseType() {
+ return databaseType;
+ }
+
+ /**
+ * @return mysqlHost
+ */
+ public String getMysqlHost() {
+ return mysqlHost;
+ }
+
+ /**
+ * @return mysqlPass
+ */
+ public String getMysqlPass() {
+ return mysqlPass;
+ }
+
+ /**
+ * @return mysqlUser
+ */
+ public String getMysqlUser() {
+ return mysqlUser;
+ }
+
+ /**
+ * @return mysqlPort
+ */
+ public int getMysqlPort() {
+ return mysqlPort;
+ }
+
+ /**
+ * @return mysqlDBName
+ */
+ public String getMysqlDBName() {
+ return mysqlDBName;
+ }
+
/**
* @return enableAttachment
*/
@@ -377,7 +443,7 @@ public List getDisableWorldsToOpenAttachBox() {
/**
* @return prohibitItemsToAttach
*/
- public List getProhibitItemsToAttach() {
+ public List getProhibitItemsToAttach() {
return prohibitItemsToAttach;
}
@@ -549,4 +615,10 @@ public List getWelcomeMailAttachments() {
return welcomeMailAttachments;
}
+ /**
+ * @return uuidOnlineMode
+ */
+ public boolean isUuidOnlineMode() {
+ return uuidOnlineMode;
+ }
}
diff --git a/src/main/java/org/bitbucket/ucchy/undine/UndineListener.java b/src/main/java/org/bitbucket/ucchy/undine/UndineListener.java
index 7549c3b..0527e21 100644
--- a/src/main/java/org/bitbucket/ucchy/undine/UndineListener.java
+++ b/src/main/java/org/bitbucket/ucchy/undine/UndineListener.java
@@ -8,7 +8,7 @@
import java.util.ArrayList;
import java.util.List;
-import org.bitbucket.ucchy.undine.item.TradableMaterial;
+import org.bitbucket.ucchy.undine.database.Database.DatabaseType;
import org.bitbucket.ucchy.undine.sender.MailSender;
import org.bitbucket.ucchy.undine.sender.MailSenderConsole;
import org.bukkit.Material;
@@ -22,6 +22,8 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
+import com.github.ucchyocean.itemconfig.ItemConfigParserV111;
+
/**
* Undineのリスナークラス
* @author ucchy
@@ -63,8 +65,8 @@ public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
UndineConfig config = parent.getUndineConfig();
- // プレイヤーキャッシュを更新する
- parent.getPlayerCache().put(player.getName(), MailSender.getMailSender(player));
+ // プレイヤーキャッシュを非同期更新する
+ parent.asyncRefreshPlayerUuid(player.getName());
// MailManagerのロードが完了していないなら、以降は何もしない
if ( !parent.getMailManager().isLoaded() ) {
@@ -72,6 +74,15 @@ public void onPlayerJoin(PlayerJoinEvent event) {
}
final MailSender sender = MailSender.getMailSender(player);
+ boolean hasPlayedBefore = player.hasPlayedBefore();
+
+ // データベースを使っている場合は、初参加のプレイヤーをデータベースに登録する。
+ if (config.getDatabaseType() != DatabaseType.FLAT_FILE) {
+ hasPlayedBefore = parent.getDatabase().mailSenderTable.exists(MailSender.getMailSender(player));
+ if (!hasPlayedBefore) {
+ parent.getDatabase().mailSenderTable.add(sender);
+ }
+ }
// 未読のメールを遅れて表示する
int delay = config.getLoginNotificationDelaySeconds();
@@ -82,7 +93,7 @@ public void run() {
}.runTaskLater(parent, delay * 20);
// 新規プレイヤーの場合は、ウェルカムメールを送る
- if ( !player.hasPlayedBefore() && config.isUseWelcomeMail() ) {
+ if ( !hasPlayedBefore && config.isUseWelcomeMail() ) {
MailSender from = MailSenderConsole.getMailSenderConsole();
List to = new ArrayList();
to.add(sender);
@@ -91,11 +102,18 @@ public void run() {
message.add(msg);
}
List attachments = cloneItemStackList(config.getWelcomeMailAttachments());
- final MailData mail = new MailData(to, from, message, attachments);
+ MailManager manager = parent.getMailManager();
int welcomeDelay = config.getWelcomeMailDelaySeconds();
new BukkitRunnable() {
public void run() {
- parent.getMailManager().sendNewMail(mail);
+ // メールの作成と送信の処理が離れすぎると
+ // その間にメールが送信されたときにIndexが競合して
+ // 最終的にNPEが発生するため、作成と送信は同時にする。
+ final MailData mail = manager.makeEditmodeMail(from);
+ mail.addTo(to);
+ mail.setMessage(message);
+ mail.setAttachments(attachments);
+ manager.sendNewMail(mail);
}
}.runTaskLater(parent, welcomeDelay * 20);
}
@@ -134,7 +152,7 @@ public void onInventoryClick(InventoryClickEvent event) {
case HOTBAR_SWAP:
case HOTBAR_MOVE_AND_READD:
ItemStack hotbar = player.getInventory().getItem(event.getHotbarButton());
- if ( hotbar.getType() != Material.AIR ) {
+ if ( hotbar != null && hotbar.getType() != Material.AIR ) {
event.setCancelled(true);
}
return;
@@ -145,7 +163,7 @@ public void onInventoryClick(InventoryClickEvent event) {
} else if ( parent.getBoxManager().isOpeningEditmodeBox(player) ) {
// 編集メールの添付ボックスのアイテム処理
- List disables
+ List disables
= parent.getUndineConfig().getProhibitItemsToAttach();
// 禁止アイテムが設定されていないなら何もしない
@@ -162,17 +180,29 @@ public void onInventoryClick(InventoryClickEvent event) {
case PLACE_ONE:
case PLACE_SOME:
case SWAP_WITH_CURSOR:
- if ( inside && isDisableItem(event.getCursor() ) ) {
- event.setCancelled(true);
- player.sendMessage(Messages.get("ErrorProhibitItemAttached",
- "%material", event.getCursor().getType().toString()));
+ if ( inside ) {
+ ItemStack cursor = event.getCursor();
+ if ( cursor != null && isDisableItem(cursor) ) {
+ event.setCancelled(true);
+ player.sendMessage(Messages.get("ErrorProhibitItemAttached",
+ "%material", cursor.getType().toString()));
+ } else if ( cursor != null && containsDisableItemInShulkerBox(cursor) ) {
+ event.setCancelled(true);
+ player.sendMessage(Messages.get("ErrorContainsProhibitItemInShulkerbox"));
+ }
}
return;
case MOVE_TO_OTHER_INVENTORY:
- if ( !inside && isDisableItem(event.getCurrentItem()) ) {
- event.setCancelled(true);
- player.sendMessage(Messages.get("ErrorProhibitItemAttached",
- "%material", event.getCurrentItem().getType().toString()));
+ if ( !inside ) {
+ ItemStack current = event.getCurrentItem();
+ if ( current != null && isDisableItem(current) ) {
+ event.setCancelled(true);
+ player.sendMessage(Messages.get("ErrorProhibitItemAttached",
+ "%material", current.getType().toString()));
+ } else if ( current != null && containsDisableItemInShulkerBox(current) ) {
+ event.setCancelled(true);
+ player.sendMessage(Messages.get("ErrorContainsProhibitItemInShulkerbox"));
+ }
}
return;
case HOTBAR_SWAP:
@@ -182,6 +212,9 @@ public void onInventoryClick(InventoryClickEvent event) {
event.setCancelled(true);
player.sendMessage(Messages.get("ErrorProhibitItemAttached",
"%material", hotbar.getType().toString()));
+ } else if ( containsDisableItemInShulkerBox(hotbar) ) {
+ event.setCancelled(true);
+ player.sendMessage(Messages.get("ErrorContainsProhibitItemInShulkerbox"));
}
return;
default:
@@ -214,7 +247,7 @@ public void onInventoryDrag(InventoryDragEvent event) {
} else if ( parent.getBoxManager().isOpeningEditmodeBox(player) ) {
// 編集メールの添付ボックスのアイテム処理
- List disables
+ List disables
= parent.getUndineConfig().getProhibitItemsToAttach();
// 禁止アイテムが設定されていないなら何もしない
@@ -223,7 +256,8 @@ public void onInventoryDrag(InventoryDragEvent event) {
}
// 禁止アイテムに関する操作でなければ何もしない
- if ( !isDisableItem(event.getOldCursor()) ) {
+ boolean isShulkerboxContainsDisableItem = containsDisableItemInShulkerBox(event.getOldCursor());
+ if ( !isDisableItem(event.getOldCursor()) && !isShulkerboxContainsDisableItem ) {
return;
}
@@ -232,8 +266,12 @@ public void onInventoryDrag(InventoryDragEvent event) {
for ( int i : event.getRawSlots() ) {
if ( i < size ) {
event.setCancelled(true);
- player.sendMessage(Messages.get("ErrorProhibitItemAttached",
- "%material", event.getOldCursor().getType().toString()));
+ if ( !isShulkerboxContainsDisableItem ) {
+ player.sendMessage(Messages.get("ErrorProhibitItemAttached",
+ "%material", event.getOldCursor().getType().toString()));
+ } else {
+ player.sendMessage(Messages.get("ErrorContainsProhibitItemInShulkerbox"));
+ }
return;
}
}
@@ -260,11 +298,33 @@ private static List