diff --git a/L2J_Mobius_C4_ScionsOfDestiny/dist/db_installer/sql/game/custom_mail.sql b/L2J_Mobius_C4_ScionsOfDestiny/dist/db_installer/sql/game/custom_mail.sql
new file mode 100644
index 0000000000..59cb8b5cfa
--- /dev/null
+++ b/L2J_Mobius_C4_ScionsOfDestiny/dist/db_installer/sql/game/custom_mail.sql
@@ -0,0 +1,7 @@
+CREATE TABLE IF NOT EXISTS `custom_mail` (
+ `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `receiver` INT UNSIGNED NOT NULL DEFAULT 0,
+ `subject` TINYTEXT NOT NULL,
+ `message` TEXT NOT NULL,
+ `items` TEXT NOT NULL -- format: itemId1 count1;itemId2 count2;itemId3 count3...
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_C4_ScionsOfDestiny/dist/game/config/custom/CustomMailManager.ini b/L2J_Mobius_C4_ScionsOfDestiny/dist/game/config/custom/CustomMailManager.ini
new file mode 100644
index 0000000000..f8c3900ec4
--- /dev/null
+++ b/L2J_Mobius_C4_ScionsOfDestiny/dist/game/config/custom/CustomMailManager.ini
@@ -0,0 +1,11 @@
+# ---------------------------------------------------------------------------
+# Custom Mail Manager
+# ---------------------------------------------------------------------------
+
+# Enable/Disable sending mail through the custom_mail SQL table.
+# Default: False
+CustomMailManagerEnabled = False
+
+# Database query delay in seconds.
+# Default: 30
+DatabaseQueryDelay = 30
diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/Config.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/Config.java
index ae7e764a35..da05b926f4 100644
--- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/Config.java
@@ -89,6 +89,7 @@ public class Config
private static final String BANK_CONFIG_FILE = "./config/custom/Bank.ini";
private static final String CANCEL_SKILL_RESTORE_BUFFS_CONFIG_FILE = "./config/custom/CancelSkillRestoreBuffs.ini";
private static final String CHAMPION_CONFIG_FILE = "./config/custom/Champion.ini";
+ private static final String CUSTOM_CUSTOM_MAIL_MANAGER_CONFIG_FILE = "./config/custom/CustomMailManager.ini";
private static final String MERCHANT_ZERO_SELL_PRICE_CONFIG_FILE = "./config/custom/MerchantZeroSellPrice.ini";
private static final String OFFLINE_CONFIG_FILE = "./config/custom/Offline.ini";
private static final String OTHER_CONFIG_FILE = "./config/custom/Other.ini";
@@ -454,6 +455,9 @@ public class Config
public static int CHAMPION_REWARD_QTY;
public static String CHAMP_TITLE;
+ public static boolean CUSTOM_MAIL_MANAGER_ENABLED;
+ public static int CUSTOM_MAIL_MANAGER_DELAY;
+
public static boolean MERCHANT_ZERO_SELL_PRICE;
public static boolean ALLOW_WEDDING;
@@ -1623,6 +1627,13 @@ public class Config
CHAMP_TITLE = championConfig.getString("ChampionTitle", "Champion");
}
+ public static void loadCustomMailManagerConfig()
+ {
+ final PropertiesParser customMailManagerConfig = new PropertiesParser(CUSTOM_CUSTOM_MAIL_MANAGER_CONFIG_FILE);
+ CUSTOM_MAIL_MANAGER_ENABLED = customMailManagerConfig.getBoolean("CustomMailManagerEnabled", false);
+ CUSTOM_MAIL_MANAGER_DELAY = customMailManagerConfig.getInt("DatabaseQueryDelay", 30) * 1000;
+ }
+
public static void loadMerchantZeroPriceConfig()
{
final PropertiesParser merchantZeroSellPriceConfig = new PropertiesParser(MERCHANT_ZERO_SELL_PRICE_CONFIG_FILE);
@@ -3058,6 +3069,7 @@ public class Config
// Custom
loadCancelSkillRestoreBuffsConfig();
loadChampionConfig();
+ loadCustomMailManagerConfig();
loadMerchantZeroPriceConfig();
loadWeddingConfig();
loadRebirthConfig();
diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/GameServer.java
index 357db12c44..30f6b6b266 100644
--- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/GameServer.java
@@ -87,6 +87,7 @@ import org.l2jmobius.gameserver.instancemanager.ClanHallManager;
import org.l2jmobius.gameserver.instancemanager.ClassDamageManager;
import org.l2jmobius.gameserver.instancemanager.CoupleManager;
import org.l2jmobius.gameserver.instancemanager.CrownManager;
+import org.l2jmobius.gameserver.instancemanager.CustomMailManager;
import org.l2jmobius.gameserver.instancemanager.DayNightSpawnManager;
import org.l2jmobius.gameserver.instancemanager.DimensionalRiftManager;
import org.l2jmobius.gameserver.instancemanager.FortManager;
@@ -361,6 +362,11 @@ public class GameServer
// Schedule auto opening/closing doors.
DoorData.getInstance().checkAutoOpen();
+ if (Config.CUSTOM_MAIL_MANAGER_ENABLED)
+ {
+ CustomMailManager.getInstance();
+ }
+
Util.printSection("Scripts");
if (!Config.ALT_DEV_NO_SCRIPT)
{
diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/instancemanager/CustomMailManager.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/instancemanager/CustomMailManager.java
new file mode 100644
index 0000000000..13557aa5d4
--- /dev/null
+++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/instancemanager/CustomMailManager.java
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.instancemanager;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.concurrent.ThreadPool;
+import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
+import org.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author Mobius
+ */
+public class CustomMailManager
+{
+ private static final Logger LOGGER = Logger.getLogger(CustomMailManager.class.getName());
+
+ // SQL Statements
+ private static final String READ_SQL = "SELECT * FROM custom_mail";
+ private static final String DELETE_SQL = "DELETE FROM custom_mail WHERE date=? AND receiver=?";
+
+ protected CustomMailManager()
+ {
+ ThreadPool.scheduleAtFixedRate(() ->
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ Statement ps = con.createStatement();
+ ResultSet rs = ps.executeQuery(READ_SQL))
+ {
+ while (rs.next())
+ {
+ final int playerId = rs.getInt("receiver");
+ final PlayerInstance player = World.getInstance().getPlayer(playerId);
+ if ((player != null) && player.isOnline())
+ {
+ // Create message.
+ final String items = rs.getString("items");
+ player.sendPacket(new CreatureSay(0, ChatType.WHISPER, rs.getString("subject"), rs.getString("message")));
+ final List itemHolders = new ArrayList<>();
+ for (String str : items.split(";"))
+ {
+ if (str.contains(" "))
+ {
+ final String itemId = str.split(" ")[0];
+ final String itemCount = str.split(" ")[1];
+ if (Util.isDigit(itemId) && Util.isDigit(itemCount))
+ {
+ itemHolders.add(new ItemHolder(Integer.parseInt(itemId), Long.parseLong(itemCount)));
+ }
+ }
+ else if (Util.isDigit(str))
+ {
+ itemHolders.add(new ItemHolder(Integer.parseInt(str), 1));
+ }
+ }
+ if (!itemHolders.isEmpty())
+ {
+ for (ItemHolder itemHolder : itemHolders)
+ {
+ player.addItem("Custom-Mail", itemHolder.getId(), (int) itemHolder.getCount(), null, true);
+ }
+ }
+
+ // Delete entry from database.
+ try (PreparedStatement stmt = con.prepareStatement(DELETE_SQL))
+ {
+ stmt.setString(1, rs.getString("date"));
+ stmt.setInt(2, playerId);
+ stmt.execute();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting entry from database: ", e);
+ }
+
+ LOGGER.info(getClass().getSimpleName() + ": Message sent to " + player.getName() + ".");
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error reading from database: ", e);
+ }
+ }, Config.CUSTOM_MAIL_MANAGER_DELAY, Config.CUSTOM_MAIL_MANAGER_DELAY);
+
+ LOGGER.info(getClass().getSimpleName() + ": Enabled.");
+ }
+
+ public static CustomMailManager getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final CustomMailManager INSTANCE = new CustomMailManager();
+ }
+}
diff --git a/L2J_Mobius_C6_Interlude/dist/db_installer/sql/game/custom_mail.sql b/L2J_Mobius_C6_Interlude/dist/db_installer/sql/game/custom_mail.sql
new file mode 100644
index 0000000000..59cb8b5cfa
--- /dev/null
+++ b/L2J_Mobius_C6_Interlude/dist/db_installer/sql/game/custom_mail.sql
@@ -0,0 +1,7 @@
+CREATE TABLE IF NOT EXISTS `custom_mail` (
+ `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `receiver` INT UNSIGNED NOT NULL DEFAULT 0,
+ `subject` TINYTEXT NOT NULL,
+ `message` TEXT NOT NULL,
+ `items` TEXT NOT NULL -- format: itemId1 count1;itemId2 count2;itemId3 count3...
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_C6_Interlude/dist/game/config/custom/CustomMailManager.ini b/L2J_Mobius_C6_Interlude/dist/game/config/custom/CustomMailManager.ini
new file mode 100644
index 0000000000..f8c3900ec4
--- /dev/null
+++ b/L2J_Mobius_C6_Interlude/dist/game/config/custom/CustomMailManager.ini
@@ -0,0 +1,11 @@
+# ---------------------------------------------------------------------------
+# Custom Mail Manager
+# ---------------------------------------------------------------------------
+
+# Enable/Disable sending mail through the custom_mail SQL table.
+# Default: False
+CustomMailManagerEnabled = False
+
+# Database query delay in seconds.
+# Default: 30
+DatabaseQueryDelay = 30
diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/Config.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/Config.java
index 89b5622ca3..0d3b65b882 100644
--- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/Config.java
@@ -90,6 +90,7 @@ public class Config
private static final String BANK_CONFIG_FILE = "./config/custom/Bank.ini";
private static final String CANCEL_SKILL_RESTORE_BUFFS_CONFIG_FILE = "./config/custom/CancelSkillRestoreBuffs.ini";
private static final String CHAMPION_CONFIG_FILE = "./config/custom/Champion.ini";
+ private static final String CUSTOM_CUSTOM_MAIL_MANAGER_CONFIG_FILE = "./config/custom/CustomMailManager.ini";
private static final String MERCHANT_ZERO_SELL_PRICE_CONFIG_FILE = "./config/custom/MerchantZeroSellPrice.ini";
private static final String OFFLINE_CONFIG_FILE = "./config/custom/Offline.ini";
private static final String OTHER_CONFIG_FILE = "./config/custom/Other.ini";
@@ -473,6 +474,9 @@ public class Config
public static int CHAMPION_REWARD_QTY;
public static String CHAMP_TITLE;
+ public static boolean CUSTOM_MAIL_MANAGER_ENABLED;
+ public static int CUSTOM_MAIL_MANAGER_DELAY;
+
public static boolean MERCHANT_ZERO_SELL_PRICE;
public static boolean ALLOW_WEDDING;
@@ -1673,6 +1677,13 @@ public class Config
CHAMP_TITLE = championConfig.getString("ChampionTitle", "Champion");
}
+ public static void loadCustomMailManagerConfig()
+ {
+ final PropertiesParser customMailManagerConfig = new PropertiesParser(CUSTOM_CUSTOM_MAIL_MANAGER_CONFIG_FILE);
+ CUSTOM_MAIL_MANAGER_ENABLED = customMailManagerConfig.getBoolean("CustomMailManagerEnabled", false);
+ CUSTOM_MAIL_MANAGER_DELAY = customMailManagerConfig.getInt("DatabaseQueryDelay", 30) * 1000;
+ }
+
public static void loadMerchantZeroPriceConfig()
{
final PropertiesParser merchantZeroSellPriceConfig = new PropertiesParser(MERCHANT_ZERO_SELL_PRICE_CONFIG_FILE);
@@ -3127,6 +3138,7 @@ public class Config
// Custom
loadCancelSkillRestoreBuffsConfig();
loadChampionConfig();
+ loadCustomMailManagerConfig();
loadMerchantZeroPriceConfig();
loadWeddingConfig();
loadRebirthConfig();
diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/GameServer.java
index 7b620245f3..8baa117582 100644
--- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/GameServer.java
@@ -89,6 +89,7 @@ import org.l2jmobius.gameserver.instancemanager.ClassDamageManager;
import org.l2jmobius.gameserver.instancemanager.CoupleManager;
import org.l2jmobius.gameserver.instancemanager.CrownManager;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
+import org.l2jmobius.gameserver.instancemanager.CustomMailManager;
import org.l2jmobius.gameserver.instancemanager.DayNightSpawnManager;
import org.l2jmobius.gameserver.instancemanager.DimensionalRiftManager;
import org.l2jmobius.gameserver.instancemanager.DuelManager;
@@ -368,6 +369,11 @@ public class GameServer
// Schedule auto opening/closing doors.
DoorData.getInstance().checkAutoOpen();
+ if (Config.CUSTOM_MAIL_MANAGER_ENABLED)
+ {
+ CustomMailManager.getInstance();
+ }
+
Util.printSection("Scripts");
if (!Config.ALT_DEV_NO_SCRIPT)
{
diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/instancemanager/CustomMailManager.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/instancemanager/CustomMailManager.java
new file mode 100644
index 0000000000..13557aa5d4
--- /dev/null
+++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/instancemanager/CustomMailManager.java
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.instancemanager;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.concurrent.ThreadPool;
+import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.model.World;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
+import org.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author Mobius
+ */
+public class CustomMailManager
+{
+ private static final Logger LOGGER = Logger.getLogger(CustomMailManager.class.getName());
+
+ // SQL Statements
+ private static final String READ_SQL = "SELECT * FROM custom_mail";
+ private static final String DELETE_SQL = "DELETE FROM custom_mail WHERE date=? AND receiver=?";
+
+ protected CustomMailManager()
+ {
+ ThreadPool.scheduleAtFixedRate(() ->
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ Statement ps = con.createStatement();
+ ResultSet rs = ps.executeQuery(READ_SQL))
+ {
+ while (rs.next())
+ {
+ final int playerId = rs.getInt("receiver");
+ final PlayerInstance player = World.getInstance().getPlayer(playerId);
+ if ((player != null) && player.isOnline())
+ {
+ // Create message.
+ final String items = rs.getString("items");
+ player.sendPacket(new CreatureSay(0, ChatType.WHISPER, rs.getString("subject"), rs.getString("message")));
+ final List itemHolders = new ArrayList<>();
+ for (String str : items.split(";"))
+ {
+ if (str.contains(" "))
+ {
+ final String itemId = str.split(" ")[0];
+ final String itemCount = str.split(" ")[1];
+ if (Util.isDigit(itemId) && Util.isDigit(itemCount))
+ {
+ itemHolders.add(new ItemHolder(Integer.parseInt(itemId), Long.parseLong(itemCount)));
+ }
+ }
+ else if (Util.isDigit(str))
+ {
+ itemHolders.add(new ItemHolder(Integer.parseInt(str), 1));
+ }
+ }
+ if (!itemHolders.isEmpty())
+ {
+ for (ItemHolder itemHolder : itemHolders)
+ {
+ player.addItem("Custom-Mail", itemHolder.getId(), (int) itemHolder.getCount(), null, true);
+ }
+ }
+
+ // Delete entry from database.
+ try (PreparedStatement stmt = con.prepareStatement(DELETE_SQL))
+ {
+ stmt.setString(1, rs.getString("date"));
+ stmt.setInt(2, playerId);
+ stmt.execute();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting entry from database: ", e);
+ }
+
+ LOGGER.info(getClass().getSimpleName() + ": Message sent to " + player.getName() + ".");
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error reading from database: ", e);
+ }
+ }, Config.CUSTOM_MAIL_MANAGER_DELAY, Config.CUSTOM_MAIL_MANAGER_DELAY);
+
+ LOGGER.info(getClass().getSimpleName() + ": Enabled.");
+ }
+
+ public static CustomMailManager getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final CustomMailManager INSTANCE = new CustomMailManager();
+ }
+}