Premium manager rework.

Contributed by yksdtc.
This commit is contained in:
MobiusDev 2017-01-03 07:35:35 +00:00
parent d39620bcb5
commit b40bd1c34b
7 changed files with 179 additions and 194 deletions

View File

@ -17,6 +17,7 @@
package handlers.admincommandhandlers; package handlers.admincommandhandlers;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;
import com.l2jmobius.Config; import com.l2jmobius.Config;
import com.l2jmobius.gameserver.cache.HtmCache; import com.l2jmobius.gameserver.cache.HtmCache;
@ -118,15 +119,21 @@ public class AdminPremium implements IAdminCommandHandler
} }
// TODO: Add check if account exists XD // TODO: Add check if account exists XD
PremiumManager.getInstance().addPremiumMonths(months, accountName); PremiumManager.getInstance().addPremiumTime(accountName, months * 30, TimeUnit.DAYS);
admin.sendMessage("Account " + accountName + " will now have premium status until " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(PremiumManager.getInstance().getPremiumEndDate(accountName)) + "."); admin.sendMessage("Account " + accountName + " will now have premium status until " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(PremiumManager.getInstance().getPremiumExpiration(accountName)) + ".");
} }
private void viewPremiumInfo(L2PcInstance admin, String accountName) private void viewPremiumInfo(L2PcInstance admin, String accountName)
{ {
if (PremiumManager.getInstance().getPremiumEndDate(accountName) > 0) if (!Config.PREMIUM_SYSTEM_ENABLED)
{ {
admin.sendMessage("Account " + accountName + " has premium status until " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(PremiumManager.getInstance().getPremiumEndDate(accountName)) + "."); admin.sendMessage("Premium system is disabled.");
return;
}
if (PremiumManager.getInstance().getPremiumExpiration(accountName) > 0)
{
admin.sendMessage("Account " + accountName + " has premium status until " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(PremiumManager.getInstance().getPremiumExpiration(accountName)) + ".");
} }
else else
{ {
@ -136,7 +143,13 @@ public class AdminPremium implements IAdminCommandHandler
private void removePremium(L2PcInstance admin, String accountName) private void removePremium(L2PcInstance admin, String accountName)
{ {
if (PremiumManager.getInstance().getPremiumEndDate(accountName) > 0) if (!Config.PREMIUM_SYSTEM_ENABLED)
{
admin.sendMessage("Premium system is disabled.");
return;
}
if (PremiumManager.getInstance().getPremiumExpiration(accountName) > 0)
{ {
PremiumManager.getInstance().removePremiumStatus(accountName); PremiumManager.getInstance().removePremiumStatus(accountName);
admin.sendMessage("Account " + accountName + " has no longer premium status."); admin.sendMessage("Account " + accountName + " has no longer premium status.");

View File

@ -20,6 +20,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;
import com.l2jmobius.Config; import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.database.DatabaseFactory;
@ -242,8 +243,8 @@ public final class HomeBoard implements IParseBoardHandler
else else
{ {
activeChar.destroyItemByItemId("CB_Premium", Config.COMMUNITY_PREMIUM_COIN_ID, Config.COMMUNITY_PREMIUM_PRICE_PER_DAY * premiumDays, activeChar, true); activeChar.destroyItemByItemId("CB_Premium", Config.COMMUNITY_PREMIUM_COIN_ID, Config.COMMUNITY_PREMIUM_PRICE_PER_DAY * premiumDays, activeChar, true);
PremiumManager.getInstance().addPremiumDays(premiumDays, activeChar.getAccountName()); PremiumManager.getInstance().addPremiumTime(activeChar.getAccountName(), premiumDays, TimeUnit.DAYS);
activeChar.sendMessage("Your account will now have premium status until " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(PremiumManager.getInstance().getPremiumEndDate(activeChar.getAccountName())) + "."); activeChar.sendMessage("Your account will now have premium status until " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(PremiumManager.getInstance().getPremiumExpiration(activeChar.getAccountName())) + ".");
CommunityBoardHandler.separateAndSend(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/premium/thankyou.html"), activeChar); CommunityBoardHandler.separateAndSend(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/premium/thankyou.html"), activeChar);
} }
} }

View File

@ -37,7 +37,7 @@ public class Premium implements IVoicedCommandHandler
if (command.startsWith("premium") && Config.PREMIUM_SYSTEM_ENABLED) if (command.startsWith("premium") && Config.PREMIUM_SYSTEM_ENABLED)
{ {
final SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm"); final SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm");
final long endDate = PremiumManager.getInstance().getPremiumEndDate(activeChar.getAccountName()); final long endDate = PremiumManager.getInstance().getPremiumExpiration(activeChar.getAccountName());
final NpcHtmlMessage msg = new NpcHtmlMessage(5); final NpcHtmlMessage msg = new NpcHtmlMessage(5);
final StringBuilder html = new StringBuilder(); final StringBuilder html = new StringBuilder();
if (endDate == 0) if (endDate == 0)

View File

@ -264,11 +264,12 @@ public class GameServer
{ {
FactionManager.getInstance(); FactionManager.getInstance();
} }
if (Config.PREMIUM_SYSTEM_ENABLED) if (Config.PREMIUM_SYSTEM_ENABLED)
{ {
LOGGER.info("PremiumManager: Premium system is enabled.");
PremiumManager.getInstance(); PremiumManager.getInstance();
} }
printSection("Clans"); printSection("Clans");
ClanTable.getInstance(); ClanTable.getInstance();
ResidenceFunctionsData.getInstance(); ResidenceFunctionsData.getInstance();

View File

@ -20,142 +20,204 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Calendar; import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.events.Containers;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogin;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.network.serverpackets.ExBrPremiumState;
/** /**
* @author Mobius * @author Mobius
*/ */
public class PremiumManager public class PremiumManager
{ {
public long getPremiumEndDate(String accountName) private final static Logger LOGGER = Logger.getLogger(PremiumManager.class.getName());
{
long endDate = 0;
try (Connection con = DatabaseFactory.getInstance().getConnection()) // SQL Statement
private final static String LOAD_SQL = "SELECT account_name,enddate FROM account_premium";
private final static String UPDATE_SQL = "UPDATE account_premium SET enddate = ? WHERE account_name = ?";
private final static String ADD_SQL = "INSERT INTO account_premium (endate,account_name) VALUE (?,?)";
class PremiumExpireTask implements Runnable
{
final L2PcInstance player;
PremiumExpireTask(L2PcInstance player)
{
this.player = player;
}
@Override
public void run()
{
player.setPremiumStatus(false);
player.sendPacket(new ExBrPremiumState(player));
}
}
// Data Cache
private final Map<String, Long> premiumData = new HashMap<>();
// expireTasks
private final Map<String, ScheduledFuture<?>> expiretasks = new HashMap<>();
// Listeners
private final ListenersContainer listenerContainer = Containers.Players();
private final Consumer<OnPlayerLogin> playerLoginEvent = (event) ->
{
final L2PcInstance player = event.getActiveChar();
final String accountName = player.getAccountName();
final long now = System.currentTimeMillis();
final long premiumExpiration = getPremiumExpiration(accountName);
player.setPremiumStatus(premiumExpiration > now);
player.sendPacket(new ExBrPremiumState(player));
if (player.hasPremiumStatus())
{
startExpireTask(player, premiumExpiration - now);
}
};
private final Consumer<OnPlayerLogout> playerLogoutEvent = (event) ->
{
L2PcInstance player = event.getActiveChar();
stopExpireTask(player);
};
protected PremiumManager()
{
loadPremiumData();
listenerContainer.addListener(new ConsumerEventListener(listenerContainer, EventType.ON_PLAYER_LOGIN, playerLoginEvent, this));
listenerContainer.addListener(new ConsumerEventListener(listenerContainer, EventType.ON_PLAYER_LOGOUT, playerLogoutEvent, this));
}
/**
* @param player
* @param delay
*/
private void startExpireTask(L2PcInstance player, long delay)
{
ScheduledFuture<?> task = ThreadPoolManager.getInstance().scheduleEvent(new PremiumExpireTask(player), delay);
expiretasks.put(player.getAccountName(), task);
}
/**
* @param player
*/
private void stopExpireTask(L2PcInstance player)
{
ScheduledFuture<?> task = expiretasks.remove(player.getAccountName());
if (task != null)
{
task.cancel(false);
task = null;
}
}
private void loadPremiumData()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(LOAD_SQL);
ResultSet rset = statement.executeQuery())
{ {
final PreparedStatement statement = con.prepareStatement("SELECT premium_service,enddate FROM account_premium WHERE account_name=?");
statement.setString(1, accountName);
final ResultSet rset = statement.executeQuery();
while (rset.next()) while (rset.next())
{ {
if (Config.PREMIUM_SYSTEM_ENABLED) premiumData.put(rset.getString(1), rset.getLong(2));
{
endDate = rset.getLong("enddate");
if (endDate <= System.currentTimeMillis())
{
endDate = 0;
removePremiumStatus(accountName);
} }
} }
}
statement.close();
}
catch (Exception e)
{
}
return endDate;
}
public void addPremiumDays(int days, String accountName)
{
long remainingTime = getPremiumEndDate(accountName);
if (remainingTime > 0)
{
remainingTime -= System.currentTimeMillis();
}
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
final Calendar endDate = Calendar.getInstance();
endDate.setTimeInMillis(System.currentTimeMillis() + remainingTime);
endDate.set(Calendar.SECOND, 0);
endDate.add(Calendar.HOUR, 24 * days);
final PreparedStatement statement = con.prepareStatement("UPDATE account_premium SET premium_service=?,enddate=? WHERE account_name=?");
statement.setInt(1, 1);
statement.setLong(2, endDate.getTimeInMillis());
statement.setString(3, accountName);
statement.execute();
statement.close();
}
catch (SQLException e) catch (SQLException e)
{ {
e.printStackTrace();
} }
for (L2PcInstance player : L2World.getInstance().getPlayers()) long expiredData = premiumData.values().stream().filter(d -> d < System.currentTimeMillis()).count();
{ LOGGER.info(getClass().getSimpleName() + ": Loaded " + premiumData.size() + " premium data (" + expiredData + " have expired)");
if (player.getAccountNamePlayer().equalsIgnoreCase(accountName))
{
player.setPremiumStatus(getPremiumEndDate(accountName) > 0);
}
}
} }
public void addPremiumMonths(int months, String accountName) public long getPremiumExpiration(String accountName)
{ {
long remainingTime = getPremiumEndDate(accountName); return premiumData.getOrDefault(accountName, 0L);
if (remainingTime > 0)
{
remainingTime -= System.currentTimeMillis();
} }
try (Connection con = DatabaseFactory.getInstance().getConnection()) public void addPremiumTime(String accountName, int timeValue, TimeUnit timeUnit)
{ {
final Calendar endDate = Calendar.getInstance(); long addTime = timeUnit.toMillis(timeValue);
endDate.setTimeInMillis(System.currentTimeMillis() + remainingTime); long now = System.currentTimeMillis();
endDate.set(Calendar.SECOND, 0); // new premium task at least from now
endDate.add(Calendar.MONTH, months); long oldPremiumExpiration = Math.max(now, getPremiumExpiration(accountName));
long newPremiumExpiration = oldPremiumExpiration + addTime;
final PreparedStatement statement = con.prepareStatement("UPDATE account_premium SET premium_service=?,enddate=? WHERE account_name=?"); String sqlCmd = premiumData.containsKey(accountName) ? UPDATE_SQL : ADD_SQL;
statement.setInt(1, 1);
statement.setLong(2, endDate.getTimeInMillis()); // UPDATE DATABASE
statement.setString(3, accountName); try (Connection con = DatabaseFactory.getInstance().getConnection();
statement.execute(); PreparedStatement stmt = con.prepareStatement(sqlCmd))
statement.close(); {
stmt.setLong(1, newPremiumExpiration);
stmt.setString(2, accountName);
stmt.execute();
} }
catch (SQLException e) catch (SQLException e)
{ {
e.printStackTrace();
} }
for (L2PcInstance player : L2World.getInstance().getPlayers()) // UPDATE CACHE
premiumData.put(accountName, newPremiumExpiration);
// UPDATE PlAYER PREMIUMSTATUS
L2PcInstance playerOnline = L2World.getInstance().getPlayers().stream().filter(p -> accountName.equals(p.getAccountName())).findFirst().orElse(null);
if (playerOnline != null)
{ {
if (player.getAccountNamePlayer().equalsIgnoreCase(accountName)) stopExpireTask(playerOnline);
startExpireTask(playerOnline, newPremiumExpiration - now);
if (!playerOnline.hasPremiumStatus())
{ {
player.setPremiumStatus(getPremiumEndDate(accountName) > 0); playerOnline.setPremiumStatus(true);
playerOnline.sendPacket(new ExBrPremiumState(playerOnline));
} }
} }
} }
public void removePremiumStatus(String accountName) public void removePremiumStatus(String accountName)
{ {
// TODO: Add check if account exists. XD L2PcInstance playerOnline = L2World.getInstance().getPlayers().stream().filter(p -> accountName.equals(p.getAccountName())).findFirst().orElse(null);
try (Connection con = DatabaseFactory.getInstance().getConnection()) if ((playerOnline != null) && playerOnline.hasPremiumStatus())
{ {
final PreparedStatement statement = con.prepareStatement("INSERT INTO account_premium (account_name,premium_service,enddate) values(?,?,?) ON DUPLICATE KEY UPDATE premium_service = ?, enddate = ?"); playerOnline.setPremiumStatus(false);
statement.setString(1, accountName); playerOnline.sendPacket(new ExBrPremiumState(playerOnline));
statement.setInt(2, 0); stopExpireTask(playerOnline);
statement.setLong(3, 0); }
statement.setInt(4, 0);
statement.setLong(5, 0); // UPDATE CACHE
statement.execute(); premiumData.remove(accountName);
statement.close();
// UPDATE DATABASE
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement stmt = con.prepareStatement(UPDATE_SQL))
{
stmt.setLong(1, 0L);
stmt.setString(2, accountName);
stmt.execute();
} }
catch (SQLException e) catch (SQLException e)
{ {
} e.printStackTrace();
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
if (player.getAccountNamePlayer().equalsIgnoreCase(accountName))
{
player.setPremiumStatus(false);
}
} }
} }

View File

@ -113,7 +113,6 @@ import com.l2jmobius.gameserver.instancemanager.HandysBlockCheckerManager;
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager; import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
import com.l2jmobius.gameserver.instancemanager.MatchingRoomManager; import com.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
import com.l2jmobius.gameserver.instancemanager.MentorManager; import com.l2jmobius.gameserver.instancemanager.MentorManager;
import com.l2jmobius.gameserver.instancemanager.PremiumManager;
import com.l2jmobius.gameserver.instancemanager.PunishmentManager; import com.l2jmobius.gameserver.instancemanager.PunishmentManager;
import com.l2jmobius.gameserver.instancemanager.QuestManager; import com.l2jmobius.gameserver.instancemanager.QuestManager;
import com.l2jmobius.gameserver.instancemanager.SiegeManager; import com.l2jmobius.gameserver.instancemanager.SiegeManager;
@ -369,9 +368,6 @@ public final class L2PcInstance extends L2Playable
private static final String UPDATE_CHARACTER_ACCESS = "UPDATE characters SET accesslevel = ? WHERE charId = ?"; private static final String UPDATE_CHARACTER_ACCESS = "UPDATE characters SET accesslevel = ? WHERE charId = ?";
private static final String RESTORE_CHARACTER = "SELECT * FROM characters WHERE charId=?"; private static final String RESTORE_CHARACTER = "SELECT * FROM characters WHERE charId=?";
// Character Premium System String Definitions:
private static final String RESTORE_PREMIUMSERVICE = "SELECT premium_service,enddate FROM account_premium WHERE account_name=?";
// Character Teleport Bookmark: // Character Teleport Bookmark:
private static final String INSERT_TP_BOOKMARK = "INSERT INTO character_tpbookmark (charId,Id,x,y,z,icon,tag,name) values (?,?,?,?,?,?,?,?)"; private static final String INSERT_TP_BOOKMARK = "INSERT INTO character_tpbookmark (charId,Id,x,y,z,icon,tag,name) values (?,?,?,?,?,?,?,?)";
private static final String UPDATE_TP_BOOKMARK = "UPDATE character_tpbookmark SET icon=?,tag=?,name=? where charId=? AND Id=?"; private static final String UPDATE_TP_BOOKMARK = "UPDATE character_tpbookmark SET icon=?,tag=?,name=? where charId=? AND Id=?";
@ -6490,7 +6486,6 @@ public final class L2PcInstance extends L2Playable
player = new L2PcInstance(objectId, template, rset.getString("account_name"), app); player = new L2PcInstance(objectId, template, rset.getString("account_name"), app);
player.setName(rset.getString("char_name")); player.setName(rset.getString("char_name"));
restorePremiumSystemData(player, rset.getString("account_name"));
player.setLastAccess(rset.getLong("lastAccess")); player.setLastAccess(rset.getLong("lastAccess"));
player.getStat().setExp(rset.getLong("exp")); player.getStat().setExp(rset.getLong("exp"));
@ -12876,48 +12871,6 @@ public final class L2PcInstance extends L2Playable
return Config.PREMIUM_SYSTEM_ENABLED && _premiumStatus; return Config.PREMIUM_SYSTEM_ENABLED && _premiumStatus;
} }
private static void restorePremiumSystemData(L2PcInstance player, String account)
{
boolean success = false;
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
final PreparedStatement ps = con.prepareStatement(RESTORE_PREMIUMSERVICE);
ps.setString(1, account);
final ResultSet rs = ps.executeQuery();
while (rs.next())
{
success = true;
if (Config.PREMIUM_SYSTEM_ENABLED)
{
if (rs.getLong("enddate") <= System.currentTimeMillis())
{
PremiumManager.getInstance().removePremiumStatus(account);
player.setPremiumStatus(false);
}
else
{
player.setPremiumStatus(rs.getBoolean("premium_service"));
}
}
else
{
player.setPremiumStatus(false);
}
}
ps.close();
}
catch (Exception e)
{
_log.warning("Premium System: Could not restore premium system data for " + account + "." + e);
e.printStackTrace();
}
if (!success)
{
PremiumManager.getInstance().removePremiumStatus(player.getAccountName());
player.setPremiumStatus(false);
}
}
public void setLastPetitionGmName(String gmName) public void setLastPetitionGmName(String gmName)
{ {
_lastPetitionGmName = gmName; _lastPetitionGmName = gmName;

View File

@ -1,45 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.network.serverpackets;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.network.client.OutgoingPackets;
/**
* @author GodKratos
*/
public class PremiumState implements IClientOutgoingPacket
{
private final int _objectId;
private final int _state;
public PremiumState(int objectId, int state)
{
_objectId = objectId;
_state = state;
}
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.EX_NOTICE_POST_ARRIVED.writeId(packet);
packet.writeD(_objectId);
packet.writeC(_state);
return true;
}
}