Added notification about offline revenue on join

Closes #47
This commit is contained in:
Eric 2017-03-17 23:38:54 +01:00
parent b554ef1efd
commit dd7a82b49e
10 changed files with 222 additions and 40 deletions

View File

@ -272,7 +272,7 @@ public class ShopChest extends JavaPlugin {
getServer().getPluginManager().registerEvents(new ShopUpdateListener(this), this); getServer().getPluginManager().registerEvents(new ShopUpdateListener(this), this);
getServer().getPluginManager().registerEvents(new ShopItemListener(this), this); getServer().getPluginManager().registerEvents(new ShopItemListener(this), this);
getServer().getPluginManager().registerEvents(new ShopInteractListener(this), this); getServer().getPluginManager().registerEvents(new ShopInteractListener(this), this);
getServer().getPluginManager().registerEvents(new NotifyUpdateOnJoinListener(this), this); getServer().getPluginManager().registerEvents(new NotifyPlayerOnJoinListener(this), this);
getServer().getPluginManager().registerEvents(new ChestProtectListener(this, worldGuard), this); getServer().getPluginManager().registerEvents(new ChestProtectListener(this, worldGuard), this);
if (!Utils.getServerVersion().equals("v1_8_R1")) if (!Utils.getServerVersion().equals("v1_8_R1"))

View File

@ -19,7 +19,8 @@ public enum Regex {
MUSIC_TITLE("%MUSIC-TITLE%"), MUSIC_TITLE("%MUSIC-TITLE%"),
PROPERTY("%PROPERTY%"), PROPERTY("%PROPERTY%"),
VALUE("%VALUE%"), VALUE("%VALUE%"),
EXTENDED("%EXTENDED%"); EXTENDED("%EXTENDED%"),
REVENUE("%REVENUE%");
private String name; private String name;

View File

@ -933,6 +933,7 @@ public class LanguageUtils {
messages.add(new LocalizedMessage(LocalizedMessage.Message.SELL_SUCESS_ADMIN, langConfig.getString("message.sell-success-admin", "&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a."), Regex.AMOUNT, Regex.ITEM_NAME, Regex.SELL_PRICE)); messages.add(new LocalizedMessage(LocalizedMessage.Message.SELL_SUCESS_ADMIN, langConfig.getString("message.sell-success-admin", "&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a."), Regex.AMOUNT, Regex.ITEM_NAME, Regex.SELL_PRICE));
messages.add(new LocalizedMessage(LocalizedMessage.Message.SOMEONE_BOUGHT, langConfig.getString("message.someone-bought", "&6%PLAYER% &abought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from your shop."), Regex.PLAYER, Regex.AMOUNT, Regex.ITEM_NAME, Regex.BUY_PRICE)); messages.add(new LocalizedMessage(LocalizedMessage.Message.SOMEONE_BOUGHT, langConfig.getString("message.someone-bought", "&6%PLAYER% &abought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from your shop."), Regex.PLAYER, Regex.AMOUNT, Regex.ITEM_NAME, Regex.BUY_PRICE));
messages.add(new LocalizedMessage(LocalizedMessage.Message.SOMEONE_SOLD, langConfig.getString("message.someone-sold", "&6%PLAYER% &asold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to your shop."), Regex.PLAYER, Regex.AMOUNT, Regex.ITEM_NAME, Regex.SELL_PRICE)); messages.add(new LocalizedMessage(LocalizedMessage.Message.SOMEONE_SOLD, langConfig.getString("message.someone-sold", "&6%PLAYER% &asold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to your shop."), Regex.PLAYER, Regex.AMOUNT, Regex.ITEM_NAME, Regex.SELL_PRICE));
messages.add(new LocalizedMessage(LocalizedMessage.Message.REVENUE_WHILE_OFFLINE, langConfig.getString("message.revenue-while-offline", "&6While you were offline, your shops have made a revenue of &c%REVENUE%&6."), Regex.REVENUE));
messages.add(new LocalizedMessage(LocalizedMessage.Message.NOT_ENOUGH_INVENTORY_SPACE, langConfig.getString("message.not-enough-inventory-space", "&cNot enough space in inventory."))); messages.add(new LocalizedMessage(LocalizedMessage.Message.NOT_ENOUGH_INVENTORY_SPACE, langConfig.getString("message.not-enough-inventory-space", "&cNot enough space in inventory.")));
messages.add(new LocalizedMessage(LocalizedMessage.Message.CHEST_NOT_ENOUGH_INVENTORY_SPACE, langConfig.getString("message.chest-not-enough-inventory-space", "&cShop is full."))); messages.add(new LocalizedMessage(LocalizedMessage.Message.CHEST_NOT_ENOUGH_INVENTORY_SPACE, langConfig.getString("message.chest-not-enough-inventory-space", "&cShop is full.")));
messages.add(new LocalizedMessage(LocalizedMessage.Message.NOT_ENOUGH_MONEY, langConfig.getString("message.not-enough-money", "&cNot enough money."))); messages.add(new LocalizedMessage(LocalizedMessage.Message.NOT_ENOUGH_MONEY, langConfig.getString("message.not-enough-money", "&cNot enough money.")));
@ -1180,7 +1181,7 @@ public class LanguageUtils {
if (localizedMessage.getRegexes()[i] == replacedRegex.getRegex()) { if (localizedMessage.getRegexes()[i] == replacedRegex.getRegex()) {
Regex regex = replacedRegex.getRegex(); Regex regex = replacedRegex.getRegex();
String toReplace = replacedRegex.getReplace(); String toReplace = replacedRegex.getReplace();
if (regex == Regex.BUY_PRICE || regex == Regex.SELL_PRICE || regex == Regex.MIN_PRICE || regex == Regex.CREATION_PRICE) { if (regex == Regex.BUY_PRICE || regex == Regex.SELL_PRICE || regex == Regex.MIN_PRICE || regex == Regex.CREATION_PRICE || regex == Regex.REVENUE) {
if (!toReplace.equals(getMessage(LocalizedMessage.Message.SHOP_INFO_DISABLED))) { if (!toReplace.equals(getMessage(LocalizedMessage.Message.SHOP_INFO_DISABLED))) {
double price = Double.parseDouble(toReplace); double price = Double.parseDouble(toReplace);
toReplace = plugin.getEconomy().format(price); toReplace = plugin.getEconomy().format(price);

View File

@ -68,6 +68,7 @@ public class LocalizedMessage {
SELL_SUCESS_ADMIN, SELL_SUCESS_ADMIN,
SOMEONE_BOUGHT, SOMEONE_BOUGHT,
SOMEONE_SOLD, SOMEONE_SOLD,
REVENUE_WHILE_OFFLINE,
NOT_ENOUGH_INVENTORY_SPACE, NOT_ENOUGH_INVENTORY_SPACE,
CHEST_NOT_ENOUGH_INVENTORY_SPACE, CHEST_NOT_ENOUGH_INVENTORY_SPACE,
NOT_ENOUGH_MONEY, NOT_ENOUGH_MONEY,

View File

@ -0,0 +1,70 @@
package de.epiceric.shopchest.listeners;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Regex;
import de.epiceric.shopchest.language.LanguageUtils;
import de.epiceric.shopchest.language.LocalizedMessage;
import de.epiceric.shopchest.nms.JsonBuilder;
import de.epiceric.shopchest.utils.Callback;
import de.epiceric.shopchest.utils.Permissions;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class NotifyPlayerOnJoinListener implements Listener {
private ShopChest plugin;
public NotifyPlayerOnJoinListener(ShopChest plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
final Player p = e.getPlayer();
if (plugin.isUpdateNeeded()) {
if (p.hasPermission(Permissions.UPDATE_NOTIFICATION)) {
JsonBuilder jb = new JsonBuilder(plugin, LanguageUtils.getMessage(LocalizedMessage.Message.UPDATE_AVAILABLE, new LocalizedMessage.ReplacedRegex(Regex.VERSION, plugin.getLatestVersion())), LanguageUtils.getMessage(LocalizedMessage.Message.UPDATE_CLICK_TO_DOWNLOAD), plugin.getDownloadLink());
jb.sendJson(p);
}
}
plugin.getShopDatabase().getLastLogout(p, new Callback(plugin) {
@Override
public void onResult(Object result) {
if (result instanceof Long) {
long lastLogout = (long) result;
if (lastLogout < 0) {
p.sendMessage(LanguageUtils.getMessage(LocalizedMessage.Message.ERROR_OCCURRED,
new LocalizedMessage.ReplacedRegex(Regex.ERROR, "Could not get last time you logged out")));
return;
}
plugin.getShopDatabase().getRevenue(p, lastLogout, new Callback(plugin) {
@Override
public void onResult(Object result) {
if (result instanceof Double) {
double revenue = (double) result;
if (revenue != 0) {
p.sendMessage(LanguageUtils.getMessage(LocalizedMessage.Message.REVENUE_WHILE_OFFLINE,
new LocalizedMessage.ReplacedRegex(Regex.REVENUE, String.valueOf(revenue))));
}
}
}
});
}
}
});
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
long time = System.currentTimeMillis();
plugin.getShopDatabase().logLogout(e.getPlayer(), time, null);
}
}

View File

@ -1,35 +0,0 @@
package de.epiceric.shopchest.listeners;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Regex;
import de.epiceric.shopchest.language.LanguageUtils;
import de.epiceric.shopchest.language.LocalizedMessage;
import de.epiceric.shopchest.nms.JsonBuilder;
import de.epiceric.shopchest.utils.Permissions;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public class NotifyUpdateOnJoinListener implements Listener {
private ShopChest plugin;
public NotifyUpdateOnJoinListener(ShopChest plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
if (plugin.isUpdateNeeded()) {
if (p.hasPermission(Permissions.UPDATE_NOTIFICATION)) {
JsonBuilder jb = new JsonBuilder(plugin, LanguageUtils.getMessage(LocalizedMessage.Message.UPDATE_AVAILABLE, new LocalizedMessage.ReplacedRegex(Regex.VERSION, plugin.getLatestVersion())), LanguageUtils.getMessage(LocalizedMessage.Message.UPDATE_CLICK_TO_DOWNLOAD), plugin.getDownloadLink());
jb.sendJson(p);
}
}
}
}

View File

@ -17,6 +17,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import java.sql.*; import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -79,6 +80,12 @@ public abstract class Database {
"`type` TINYTEXT NOT NULL" + "`type` TINYTEXT NOT NULL" +
");"; ");";
String queryCreateTablePlayerLogout =
"CREATE TABLE IF NOT EXISTS player_logout (" +
"`player` VARCHAR(36) PRIMARY KEY NOT NULL," +
"`time` LONG NOT NULL" +
");";
String queryCheckIfTableExists = String queryCheckIfTableExists =
(Database.this instanceof SQLite ? (Database.this instanceof SQLite ?
"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'shop_list'" : "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'shop_list'" :
@ -118,6 +125,11 @@ public abstract class Database {
s3.executeUpdate(queryCreateTableShopLog); s3.executeUpdate(queryCreateTableShopLog);
s3.close(); s3.close();
// Create table "player_logout"
Statement s4 = connection.createStatement();
s4.executeUpdate(queryCreateTablePlayerLogout);
s4.close();
// Count entries in table "shops" // Count entries in table "shops"
PreparedStatement ps = connection.prepareStatement("SELECT * FROM shops"); PreparedStatement ps = connection.prepareStatement("SELECT * FROM shops");
ResultSet rs2 = ps.executeQuery(); ResultSet rs2 = ps.executeQuery();
@ -365,6 +377,133 @@ public abstract class Database {
}.runTaskAsynchronously(plugin); }.runTaskAsynchronously(plugin);
} }
/**
* Get the revenue a player got while he was offline
* @param player Player whose revenue to get
* @param logoutTime Time in milliseconds when he logged out the last time
*/
public void getRevenue(final Player player, final long logoutTime, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
PreparedStatement ps = null;
ResultSet rs = null;
String vendor = String.format("%s (%s)", player.getUniqueId().toString(), player.getName());
double revenue = 0;
try {
ps = connection.prepareStatement("SELECT * FROM shop_log WHERE vendor = ?;");
ps.setString(1, vendor);
rs = ps.executeQuery();
while (rs.next()) {
if (rs.getString("vendor").equals(vendor)) {
double singleRevenue = rs.getDouble("price");
ShopBuySellEvent.Type type = ShopBuySellEvent.Type.valueOf(rs.getString("type"));
if (type == ShopBuySellEvent.Type.SELL) singleRevenue = -singleRevenue;
long timestamp;
try {
timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(rs.getString("timestamp")).getTime();
} catch (ParseException ex) {
plugin.debug("Failed to get revenue from player \"" + player.getUniqueId().toString() + "\"");
plugin.debug(ex);
continue;
}
if (timestamp > logoutTime) {
revenue += singleRevenue;
}
}
}
if (callback != null) callback.callSyncResult(revenue);
} catch (SQLException ex) {
if (callback != null) callback.callSyncError(ex);
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to get revenue from player \"" + player.getUniqueId().toString() + "\"");
plugin.debug(ex);
} finally {
close(ps, rs);
}
}
}.runTaskAsynchronously(plugin);
}
/**
* Log a logout to the database
* @param player Player who logged out
* @param timestamp Time in milliseconds when the player logged out
*/
public void logLogout(final Player player, final long timestamp, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
PreparedStatement ps = null;
try {
ps = connection.prepareStatement("REPLACE INTO player_logout (player,time) VALUES(?,?)");
ps.setString(1, player.getUniqueId().toString());
ps.setLong(2, timestamp);
ps.executeUpdate();
if (callback != null) callback.callSyncResult(null);
plugin.debug("Logged logout to database");
} catch (final SQLException ex) {
if (callback != null) callback.callSyncError(ex);
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to log logout to database");
plugin.debug(ex);
} finally {
close(ps, null);
}
}
}.runTaskAsynchronously(plugin);
}
/**
* Get the last logout of a player
* @param player Player who logged out
*/
public void getLastLogout(final Player player, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
PreparedStatement ps = null;
ResultSet rs = null;
String playerUuid = player.getUniqueId().toString();
try {
ps = connection.prepareStatement("SELECT * FROM player_logout WHERE player = ?;");
ps.setString(1, playerUuid);
rs = ps.executeQuery();
while (rs.next()) {
if (rs.getString("player").equals(playerUuid)) {
if (callback != null) callback.callSyncResult(rs.getLong("time"));
return;
}
}
if (callback != null) callback.callSyncResult(-1);
} catch (SQLException ex) {
if (callback != null) callback.callSyncError(ex);
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to get last logout from player \"" + playerUuid + "\"");
plugin.debug(ex);
} finally {
close(ps, rs);
}
}
}.runTaskAsynchronously(plugin);
}
/** /**
* Closes a {@link PreparedStatement} and a {@link ResultSet} * Closes a {@link PreparedStatement} and a {@link ResultSet}
* @param ps {@link PreparedStatement} to close * @param ps {@link PreparedStatement} to close

View File

@ -14,7 +14,7 @@ public abstract class Callback {
public void onError(Throwable throwable) {} public void onError(Throwable throwable) {}
public void callSyncResult(final Object result) { public final void callSyncResult(final Object result) {
new BukkitRunnable() { new BukkitRunnable() {
@Override @Override
public void run() { public void run() {
@ -23,7 +23,7 @@ public abstract class Callback {
}.runTask(plugin); }.runTask(plugin);
} }
public void callSyncError(final Throwable throwable) { public final void callSyncError(final Throwable throwable) {
new BukkitRunnable() { new BukkitRunnable() {
@Override @Override
public void run() { public void run() {

View File

@ -24,6 +24,7 @@ message.sell-success=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE%&a a
message.sell-success-admin=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE% &averkauft. message.sell-success-admin=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE% &averkauft.
message.someone-bought=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE%&a von deinem Shop gekauft. message.someone-bought=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE%&a von deinem Shop gekauft.
message.someone-sold=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE%&a an deinen Shop verkauft. message.someone-sold=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE%&a an deinen Shop verkauft.
message.revenue-while-offline=&6Während du offline warst, haben deine Shops einen Umsatz von &c%REVENUE%&6 gemacht.
message.not-enough-inventory-space=&cNicht genug Platz im Inventar. message.not-enough-inventory-space=&cNicht genug Platz im Inventar.
message.chest-not-enough-inventory-space=&cShop ist voll. message.chest-not-enough-inventory-space=&cShop ist voll.
message.not-enough-money=&cNicht genug Geld. message.not-enough-money=&cNicht genug Geld.

View File

@ -93,6 +93,10 @@ message.someone-bought=&6%PLAYER% &abought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-
# Usable regex: %AMOUNT%, %ITEMNAME%, %SELL-PRICE%, %PLAYER% # Usable regex: %AMOUNT%, %ITEMNAME%, %SELL-PRICE%, %PLAYER%
message.someone-sold=&6%PLAYER% &asold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to your shop. message.someone-sold=&6%PLAYER% &asold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to your shop.
# Set the message when a player joins and made a revenue while he was offline.
# Usable regex: %REVENUE%
message.revenue-while-offline=&6While you were offline, your shops have made a revenue of &c%REVENUE%&6.
# Set the message when the inventory is full when the player is buying something. # Set the message when the inventory is full when the player is buying something.
message.not-enough-inventory-space=&cNot enough space in inventory. message.not-enough-inventory-space=&cNot enough space in inventory.