From 0a69033fa0b53bf14bcad1b94ad861fcd4b6a9ef Mon Sep 17 00:00:00 2001 From: mobius <8391001+MobiusDevelopment@users.noreply.github.com> Date: Fri, 2 Jan 2015 12:18:31 +0000 Subject: [PATCH] Save offline traders in real time. --- trunk/dist/game/config/Custom.properties | 5 + trunk/java/com/l2jserver/Config.java | 2 + .../com/l2jserver/gameserver/Shutdown.java | 2 +- .../datatables/OfflineTradersTable.java | 111 +++++++++++++++++- .../gameserver/network/L2GameClient.java | 7 ++ .../network/clientpackets/EnterWorld.java | 6 + .../clientpackets/RequestPrivateStoreBuy.java | 7 ++ .../RequestPrivateStoreSell.java | 7 ++ 8 files changed, 143 insertions(+), 4 deletions(-) diff --git a/trunk/dist/game/config/Custom.properties b/trunk/dist/game/config/Custom.properties index 2d007fc602..9cc4372d06 100644 --- a/trunk/dist/game/config/Custom.properties +++ b/trunk/dist/game/config/Custom.properties @@ -308,6 +308,11 @@ OfflineMaxDays = 10 #Default: True OfflineDisconnectFinished = True +#Store offline trader transactions in realtime. +#Uses more datatabase resources, but helps if server shuts down unexpectedly. +StoreOfflineTradeInRealtime = True + + # --------------------------------------------------------------------------- # Mana Drugs/Potions # --------------------------------------------------------------------------- diff --git a/trunk/java/com/l2jserver/Config.java b/trunk/java/com/l2jserver/Config.java index 13be65f9ab..71b49e1811 100644 --- a/trunk/java/com/l2jserver/Config.java +++ b/trunk/java/com/l2jserver/Config.java @@ -767,6 +767,7 @@ public final class Config public static boolean OFFLINE_SET_NAME_COLOR; public static int OFFLINE_NAME_COLOR; public static boolean OFFLINE_FAME; + public static boolean STORE_OFFLINE_TRADE_IN_REALTIME; public static boolean L2JMOD_ENABLE_MANA_POTIONS_SUPPORT; public static boolean L2JMOD_DISPLAY_SERVER_TIME; public static boolean WELCOME_MESSAGE_ENABLED; @@ -2478,6 +2479,7 @@ public final class Config RESTORE_OFFLINERS = CustomSettings.getBoolean("RestoreOffliners", false); OFFLINE_MAX_DAYS = CustomSettings.getInt("OfflineMaxDays", 10); OFFLINE_DISCONNECT_FINISHED = CustomSettings.getBoolean("OfflineDisconnectFinished", true); + STORE_OFFLINE_TRADE_IN_REALTIME = CustomSettings.getBoolean("StoreOfflineTradeInRealtime", true); L2JMOD_ENABLE_MANA_POTIONS_SUPPORT = CustomSettings.getBoolean("EnableManaPotionSupport", false); diff --git a/trunk/java/com/l2jserver/gameserver/Shutdown.java b/trunk/java/com/l2jserver/gameserver/Shutdown.java index b7325dd3f9..f884595ddd 100644 --- a/trunk/java/com/l2jserver/gameserver/Shutdown.java +++ b/trunk/java/com/l2jserver/gameserver/Shutdown.java @@ -201,7 +201,7 @@ public class Shutdown extends Thread try { - if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS) + if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS && !Config.STORE_OFFLINE_TRADE_IN_REALTIME) { OfflineTradersTable.getInstance().storeOffliners(); _log.info("Offline Traders Table: Offline shops stored(" + tc.getEstimatedTimeAndRestartCounter() + "ms)."); diff --git a/trunk/java/com/l2jserver/gameserver/datatables/OfflineTradersTable.java b/trunk/java/com/l2jserver/gameserver/datatables/OfflineTradersTable.java index 14e8687670..496140b934 100644 --- a/trunk/java/com/l2jserver/gameserver/datatables/OfflineTradersTable.java +++ b/trunk/java/com/l2jserver/gameserver/datatables/OfflineTradersTable.java @@ -45,7 +45,9 @@ public class OfflineTradersTable private static final String SAVE_OFFLINE_STATUS = "INSERT INTO character_offline_trade (`charId`,`time`,`type`,`title`) VALUES (?,?,?,?)"; private static final String SAVE_ITEMS = "INSERT INTO character_offline_trade_items (`charId`,`item`,`count`,`price`) VALUES (?,?,?,?)"; private static final String CLEAR_OFFLINE_TABLE = "DELETE FROM character_offline_trade"; + private static final String CLEAR_OFFLINE_TABLE_PLAYER = "DELETE FROM character_offline_trade WHERE `charId`=?"; private static final String CLEAR_OFFLINE_TABLE_ITEMS = "DELETE FROM character_offline_trade_items"; + private static final String CLEAR_OFFLINE_TABLE_ITEMS_PLAYER = "DELETE FROM character_offline_trade_items WHERE `charId`=?"; private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade"; private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE charId = ?"; @@ -253,10 +255,13 @@ public class OfflineTradersTable LOGGER.info(getClass().getSimpleName() + ": Loaded: " + nTraders + " offline trader(s)"); - try (Statement stm1 = con.createStatement()) + if (!Config.STORE_OFFLINE_TRADE_IN_REALTIME) { - stm1.execute(CLEAR_OFFLINE_TABLE); - stm1.execute(CLEAR_OFFLINE_TABLE_ITEMS); + try (Statement stm1 = con.createStatement()) + { + stm1.execute(CLEAR_OFFLINE_TABLE); + stm1.execute(CLEAR_OFFLINE_TABLE_ITEMS); + } } } catch (Exception e) @@ -265,6 +270,106 @@ public class OfflineTradersTable } } + public static synchronized void onTransaction(L2PcInstance trader, boolean finished, boolean firstCall) + { + try (Connection con = L2DatabaseFactory.getInstance().getConnection(); + PreparedStatement stm1 = con.prepareStatement(CLEAR_OFFLINE_TABLE_ITEMS_PLAYER); + PreparedStatement stm2 = con.prepareStatement(CLEAR_OFFLINE_TABLE_PLAYER); + PreparedStatement stm3 = con.prepareStatement(SAVE_ITEMS); + PreparedStatement stm4 = con.prepareStatement(SAVE_OFFLINE_STATUS)) + { + String title = null; + + stm1.setInt(1, trader.getObjectId()); // Char Id + stm1.execute(); + stm1.close(); + + // Trade is done - clear info + if (finished) + { + stm2.setInt(1, trader.getObjectId()); // Char Id + stm2.execute(); + stm2.close(); + } + else + { + try + { + if ((trader.getClient() == null) || trader.getClient().isDetached()) + { + switch (trader.getPrivateStoreType()) + { + case BUY: + if (firstCall) + { + title = trader.getBuyList().getTitle(); + } + for (TradeItem i : trader.getBuyList().getItems()) + { + stm3.setInt(1, trader.getObjectId()); + stm3.setInt(2, i.getItem().getId()); + stm3.setLong(3, i.getCount()); + stm3.setLong(4, i.getPrice()); + stm3.executeUpdate(); + stm3.clearParameters(); + } + break; + case SELL: + case PACKAGE_SELL: + if (firstCall) + { + title = trader.getSellList().getTitle(); + } + for (TradeItem i : trader.getSellList().getItems()) + { + stm3.setInt(1, trader.getObjectId()); + stm3.setInt(2, i.getObjectId()); + stm3.setLong(3, i.getCount()); + stm3.setLong(4, i.getPrice()); + stm3.executeUpdate(); + stm3.clearParameters(); + } + break; + case MANUFACTURE: + if (firstCall) + { + title = trader.getStoreName(); + } + for (L2ManufactureItem i : trader.getManufactureItems().values()) + { + stm3.setInt(1, trader.getObjectId()); + stm3.setInt(2, i.getRecipeId()); + stm3.setLong(3, 0); + stm3.setLong(4, i.getCost()); + stm3.executeUpdate(); + stm3.clearParameters(); + } + } + stm3.close(); + if (firstCall) + { + stm4.setInt(1, trader.getObjectId()); // Char Id + stm4.setLong(2, trader.getOfflineStartTime()); + stm4.setInt(3, trader.getPrivateStoreType().getId()); // store type + stm4.setString(4, title); + stm4.executeUpdate(); + stm4.clearParameters(); + stm4.close(); + } + } + } + catch (Exception e) + { + LOGGER.log(Level.WARNING, "OfflineTradersTable[storeTradeItems()]: Error while saving offline trader: " + trader.getObjectId() + " " + e, e); + } + } + } + catch (Exception e) + { + LOGGER.log(Level.WARNING, "OfflineTradersTable[storeTradeItems()]: Error while saving offline traders: " + e, e); + } + } + /** * Gets the single instance of OfflineTradersTable. * @return single instance of OfflineTradersTable diff --git a/trunk/java/com/l2jserver/gameserver/network/L2GameClient.java b/trunk/java/com/l2jserver/gameserver/network/L2GameClient.java index 9ed812ab16..db04753fd1 100644 --- a/trunk/java/com/l2jserver/gameserver/network/L2GameClient.java +++ b/trunk/java/com/l2jserver/gameserver/network/L2GameClient.java @@ -44,6 +44,7 @@ import com.l2jserver.gameserver.LoginServerThread.SessionKey; import com.l2jserver.gameserver.ThreadPoolManager; import com.l2jserver.gameserver.datatables.CharNameTable; import com.l2jserver.gameserver.datatables.ClanTable; +import com.l2jserver.gameserver.datatables.OfflineTradersTable; import com.l2jserver.gameserver.datatables.SecondaryAuthData; import com.l2jserver.gameserver.instancemanager.AntiFeedManager; import com.l2jserver.gameserver.model.CharSelectInfoPackage; @@ -804,6 +805,12 @@ public final class L2GameClient extends MMOClient> i getActiveChar().setOfflineStartTime(System.currentTimeMillis()); } + // Store trade on exit, if realtime saving is enabled. + if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(getActiveChar(), false, true); + } + final LogRecord record = new LogRecord(Level.INFO, "Entering offline mode"); record.setParameters(new Object[] { diff --git a/trunk/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java b/trunk/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java index f598e09296..8cf436ea91 100644 --- a/trunk/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java +++ b/trunk/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java @@ -24,6 +24,7 @@ import com.l2jserver.gameserver.cache.HtmCache; import com.l2jserver.gameserver.datatables.AdminTable; import com.l2jserver.gameserver.datatables.AnnouncementsTable; import com.l2jserver.gameserver.datatables.BeautyShopData; +import com.l2jserver.gameserver.datatables.OfflineTradersTable; import com.l2jserver.gameserver.datatables.SkillTreesData; import com.l2jserver.gameserver.enums.Race; import com.l2jserver.gameserver.instancemanager.CHSiegeManager; @@ -575,6 +576,11 @@ public class EnterWorld extends L2GameClientPacket activeChar.sendPacket(ExNotifyPremiumItem.STATIC_PACKET); } + if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(activeChar, true, false); + } + activeChar.broadcastUserInfo(); if (BeautyShopData.getInstance().hasBeautyData(activeChar.getRace(), activeChar.getAppearance().getSexType())) diff --git a/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreBuy.java b/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreBuy.java index 673c91862c..c19e1ec0b6 100644 --- a/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreBuy.java +++ b/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreBuy.java @@ -22,6 +22,7 @@ import static com.l2jserver.gameserver.model.actor.L2Npc.INTERACTION_DISTANCE; import javolution.util.FastSet; import com.l2jserver.Config; +import com.l2jserver.gameserver.datatables.OfflineTradersTable; import com.l2jserver.gameserver.enums.PrivateStoreType; import com.l2jserver.gameserver.model.ItemRequest; import com.l2jserver.gameserver.model.L2Object; @@ -153,6 +154,12 @@ public final class RequestPrivateStoreBuy extends L2GameClientPacket return; } + // Update offline trade record, if realtime saving is enabled + if (Config.OFFLINE_TRADE_ENABLE && Config.STORE_OFFLINE_TRADE_IN_REALTIME && ((storePlayer.getClient() == null) || storePlayer.getClient().isDetached())) + { + OfflineTradersTable.onTransaction(storePlayer, storeList.getItemCount() == 0, false); + } + if (storeList.getItemCount() == 0) { storePlayer.setPrivateStoreType(PrivateStoreType.NONE); diff --git a/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreSell.java b/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreSell.java index 7f21b1411b..9dd79548b9 100644 --- a/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreSell.java +++ b/trunk/java/com/l2jserver/gameserver/network/clientpackets/RequestPrivateStoreSell.java @@ -21,6 +21,7 @@ package com.l2jserver.gameserver.network.clientpackets; import static com.l2jserver.gameserver.model.actor.L2Npc.INTERACTION_DISTANCE; import com.l2jserver.Config; +import com.l2jserver.gameserver.datatables.OfflineTradersTable; import com.l2jserver.gameserver.enums.PrivateStoreType; import com.l2jserver.gameserver.model.ItemRequest; import com.l2jserver.gameserver.model.L2World; @@ -138,6 +139,12 @@ public final class RequestPrivateStoreSell extends L2GameClientPacket return; } + // Update offline trade record, if realtime saving is enabled + if (Config.OFFLINE_TRADE_ENABLE && Config.STORE_OFFLINE_TRADE_IN_REALTIME && ((storePlayer.getClient() == null) || storePlayer.getClient().isDetached())) + { + OfflineTradersTable.onTransaction(storePlayer, storeList.getItemCount() == 0, false); + } + if (storeList.getItemCount() == 0) { storePlayer.setPrivateStoreType(PrivateStoreType.NONE);