0 Members and 1 Guest are viewing this topic.
### Eclipse Workspace Patch 1.0#P aCis_gameserverIndex: java/net/sf/l2j/gameserver/GameServer.java===================================================================--- java/net/sf/l2j/gameserver/GameServer.java (revision 219)+++ java/net/sf/l2j/gameserver/GameServer.java (working copy)@@ -51,6 +51,7 @@ import net.sf.l2j.gameserver.datatables.NobleSkillTable; import net.sf.l2j.gameserver.datatables.NpcTable; import net.sf.l2j.gameserver.datatables.NpcWalkerRoutesTable;+import net.sf.l2j.gameserver.datatables.OfflineTradersTable; import net.sf.l2j.gameserver.datatables.PetDataTable; import net.sf.l2j.gameserver.datatables.SkillTable; import net.sf.l2j.gameserver.datatables.SkillTreeTable;@@ -278,6 +279,9 @@ KnownListUpdateTaskManager.getInstance(); MovieMakerManager.getInstance(); + if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)+ OfflineTradersTable.restoreOfflineTraders();+ if (Config.DEADLOCK_DETECTOR) { _log.info("Deadlock detector is enabled. Timer: " + Config.DEADLOCK_CHECK_INTERVAL +"s.");Index: java/net/sf/l2j/gameserver/network/L2GameClient.java===================================================================--- java/net/sf/l2j/gameserver/network/L2GameClient.java (revision 219)+++ java/net/sf/l2j/gameserver/network/L2GameClient.java (working copy)@@ -26,6 +26,7 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger;+import java.util.logging.LogRecord; import net.sf.l2j.Config; import net.sf.l2j.L2DatabaseFactory;@@ -478,10 +479,20 @@ return _charSlotMapping[charslot]; } - public void close(L2GameServerPacket gsp)- {- getConnection().close(gsp);- }+ public void close(L2GameServerPacket gsp)+ {+ if (getConnection() == null)+ return; // ofline shop+ else+ getConnection().close(gsp);+ }+ + public void close(L2GameServerPacket[] gspArray)+ {+ if (getConnection() == null)+ return; // ofline shop+ getConnection().close(gspArray);+ } /** * @param charslot@@ -577,6 +588,23 @@ setDetached(true); fast = !getActiveChar().isInCombat() && !getActiveChar().isLocked(); }+ L2PcInstance player = L2GameClient.this.getActiveChar();+ if ((player.isInStoreMode() && Config.OFFLINE_TRADE_ENABLE) || (player.isInCraftMode() && Config.OFFLINE_CRAFT_ENABLE))+ {+ player.leaveParty();+ if (Config.OFFLINE_SET_NAME_COLOR)+ {+ player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR);+ player.broadcastUserInfo();+ }+ if (player.getOfflineStartTime() == 0)+ player.setOfflineStartTime(System.currentTimeMillis());+ + LogRecord record = new LogRecord(Level.INFO, "Entering offline mode");+ record.setParameters(new Object[]{L2GameClient.this});+ _log.log(record);+ return;+ } cleanMe(fast); } catch (Exception e1)Index: java/net/sf/l2j/gameserver/Shutdown.java===================================================================--- java/net/sf/l2j/gameserver/Shutdown.java (revision 219)+++ java/net/sf/l2j/gameserver/Shutdown.java (working copy)@@ -20,6 +20,7 @@ import net.sf.l2j.Config; import net.sf.l2j.L2DatabaseFactory;+import net.sf.l2j.gameserver.datatables.OfflineTradersTable; import net.sf.l2j.gameserver.instancemanager.CastleManorManager; import net.sf.l2j.gameserver.instancemanager.CursedWeaponsManager; import net.sf.l2j.gameserver.instancemanager.GrandBossManager;@@ -125,6 +126,16 @@ { if (this == SingletonHolder._instance) {+ try+ {+ if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)+ OfflineTradersTable.storeOffliners();+ }+ catch (Throwable t)+ {+ _log.log(Level.WARNING, "Error saving offline shops.",t);+ }+ Util.printSection("Under " + MODE_TEXT[_shutdownMode] + " process"); // disconnect playersIndex: java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java===================================================================--- java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java (revision 219)+++ java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java (working copy)@@ -427,6 +427,8 @@ public int _telemode = 0; private boolean _inCrystallize; private boolean _inCraftMode;+ + private long _offlineShopStart = 0; /** The table containing all L2RecipeList of the L2PcInstance */ private Map<Integer, L2RecipeList> _dwarvenRecipeBook = new FastMap<Integer, L2RecipeList>();@@ -908,8 +910,15 @@ public String getAccountName() {+ if (getClient() == null)+ return getAccountNamePlayer(); return getClient().getAccountName(); }+ + public String getAccountNamePlayer()+ {+ return _accountName;+ } public Map<Integer, String> getAccountChars() {@@ -5266,6 +5275,11 @@ public void setPrivateStoreType(int type) { _privatestore = type;+ + if (Config.OFFLINE_DISCONNECT_FINISHED && _privatestore == STORE_PRIVATE_NONE && (getClient() == null || getClient().isDetached()))+ {+ deleteMe();+ } } /**@@ -11760,4 +11774,12 @@ } } }+ public long getOfflineStartTime()+ {+ return _offlineShopStart;+ }+ public void setOfflineStartTime(long time)+ {+ _offlineShopStart = time;+ } }\ No newline at end of fileIndex: java/net/sf/l2j/Config.java===================================================================--- java/net/sf/l2j/Config.java (revision 219)+++ java/net/sf/l2j/Config.java (working copy)@@ -651,6 +651,16 @@ public static int ZONE_TOWN; public static boolean DISABLE_TUTORIAL; + /** Offline stores */+ public static boolean OFFLINE_TRADE_ENABLE;+ public static boolean OFFLINE_CRAFT_ENABLE;+ public static boolean RESTORE_OFFLINERS;+ public static int OFFLINE_MAX_DAYS;+ public static boolean OFFLINE_DISCONNECT_FINISHED;+ public static boolean OFFLINE_SET_NAME_COLOR;+ public static int OFFLINE_NAME_COLOR;+ public static boolean OFFLINE_FAME;+ //-------------------------------------------------- // Those "hidden" settings haven't configs to avoid admins to :) their server // You still can experiment changing values here. But don't say I didn't warn you.@@ -1397,6 +1407,15 @@ ZONE_TOWN = Integer.parseInt(server.getProperty("ZoneTown", "0")); SERVER_NEWS = Boolean.valueOf(server.getProperty("ShowServerNews", "False")); DISABLE_TUTORIAL = Boolean.parseBoolean(server.getProperty("DisableTutorial", "False"));+ + OFFLINE_TRADE_ENABLE = Boolean.parseBoolean(server.getProperty("OfflineTradeEnable", "false"));+ OFFLINE_CRAFT_ENABLE = Boolean.parseBoolean(server.getProperty("OfflineCraftEnable", "false"));+ OFFLINE_SET_NAME_COLOR = Boolean.parseBoolean(server.getProperty("OfflineSetNameColor", "false"));+ OFFLINE_NAME_COLOR = Integer.decode("0x" + server.getProperty("OfflineNameColor", "808080"));+ OFFLINE_FAME = Boolean.parseBoolean(server.getProperty("OfflineFame", "true"));+ RESTORE_OFFLINERS = Boolean.parseBoolean(server.getProperty("RestoreOffliners", "false"));+ OFFLINE_MAX_DAYS = Integer.parseInt(server.getProperty("OfflineMaxDays", "10"));+ OFFLINE_DISCONNECT_FINISHED = Boolean.parseBoolean(server.getProperty("OfflineDisconnectFinished", "true")); } catch (Exception e) {Index: java/net/sf/l2j/gameserver/datatables/OfflineTradersTable.java===================================================================--- java/net/sf/l2j/gameserver/datatables/OfflineTradersTable.java (revision 0)+++ java/net/sf/l2j/gameserver/datatables/OfflineTradersTable.java (revision 0)@@ -0,0 +1,274 @@+/*+ * 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 net.sf.l2j.gameserver.datatables;++import java.sql.Connection;+import java.sql.PreparedStatement;+import java.sql.ResultSet;+import java.sql.SQLException;+import java.util.Calendar;+import java.util.logging.Level;+import java.util.logging.Logger;++import net.sf.l2j.Config;+import net.sf.l2j.L2DatabaseFactory;+import net.sf.l2j.gameserver.LoginServerThread;+import net.sf.l2j.gameserver.model.L2ManufactureItem;+import net.sf.l2j.gameserver.model.L2ManufactureList;+import net.sf.l2j.gameserver.model.L2World;+import net.sf.l2j.gameserver.model.TradeList.TradeItem;+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;+import net.sf.l2j.gameserver.network.L2GameClient;+import net.sf.l2j.gameserver.network.L2GameClient.GameClientState;++public class OfflineTradersTable+{+ private static Logger _log = Logger.getLogger(OfflineTradersTable.class.getName());+ + //SQL DEFINITIONS+ 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_ITEMS = "DELETE FROM character_offline_trade_items";+ 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 = ?";+ + public static void storeOffliners()+ {+ Connection con = null;+ try+ {+ con = L2DatabaseFactory.getInstance().getConnection();+ PreparedStatement stm = con.prepareStatement(CLEAR_OFFLINE_TABLE);+ stm.execute();+ stm.close();+ stm = con.prepareStatement(CLEAR_OFFLINE_TABLE_ITEMS);+ stm.execute();+ stm.close();+ + con.setAutoCommit(false); // avoid halfway done+ stm = con.prepareStatement(SAVE_OFFLINE_STATUS);+ PreparedStatement stm_items = con.prepareStatement(SAVE_ITEMS);+ + //TextBuilder items = TextBuilder.newInstance();+ for (L2PcInstance pc : L2World.getInstance().getAllPlayers().values())+ {+ try+ {+ if ((pc.getPrivateStoreType() != L2PcInstance.STORE_PRIVATE_NONE) && (pc.getClient() == null || pc.getClient().isDetached()))+ {+ stm.setInt(1, pc.getObjectId()); //Char Id+ stm.setLong(2, pc.getOfflineStartTime());+ stm.setInt(3, pc.getPrivateStoreType()); //store type+ String title = null;+ + switch (pc.getPrivateStoreType())+ {+ case L2PcInstance.STORE_PRIVATE_BUY:+ if (!Config.OFFLINE_TRADE_ENABLE)+ continue;+ title = pc.getBuyList().getTitle();+ for (TradeItem i : pc.getBuyList().getItems())+ {+ stm_items.setInt(1, pc.getObjectId());+ stm_items.setInt(2, i.getItem().getItemId());+ stm_items.setInt(3, i.getCount());+ stm_items.setInt(4, i.getPrice());+ stm_items.executeUpdate();+ stm_items.clearParameters();+ }+ break;+ case L2PcInstance.STORE_PRIVATE_SELL:+ case L2PcInstance.STORE_PRIVATE_PACKAGE_SELL:+ if (!Config.OFFLINE_TRADE_ENABLE)+ continue;+ title = pc.getSellList().getTitle();+ for (TradeItem i : pc.getSellList().getItems())+ {+ stm_items.setInt(1, pc.getObjectId());+ stm_items.setInt(2, i.getObjectId());+ stm_items.setInt(3, i.getCount());+ stm_items.setInt(4, i.getPrice());+ stm_items.executeUpdate();+ stm_items.clearParameters();+ }+ break;+ case L2PcInstance.STORE_PRIVATE_MANUFACTURE:+ if (!Config.OFFLINE_CRAFT_ENABLE)+ continue;+ title = pc.getCreateList().getStoreName();+ for (L2ManufactureItem i : pc.getCreateList().getList())+ {+ stm_items.setInt(1, pc.getObjectId());+ stm_items.setInt(2, i.getRecipeId());+ stm_items.setLong(3, 0);+ stm_items.setLong(4, i.getCost());+ stm_items.executeUpdate();+ stm_items.clearParameters();+ }+ }+ stm.setString(4, title);+ stm.executeUpdate();+ stm.clearParameters();+ con.commit(); // flush+ }+ }+ catch (Exception e)+ {+ _log.log(Level.WARNING, "OfflineTradersTable[storeTradeItems()]: Error while saving offline trader: " + pc.getObjectId() + " " + e, e);+ }+ }+ stm.close();+ stm_items.close();+ _log.info("Offline traders stored.");+ }+ catch (Exception e)+ {+ _log.log(Level.WARNING,"OfflineTradersTable[storeTradeItems()]: Error while saving offline traders: " + e,e);+ }+ finally+ {+ try+ {+ con.close();+ } catch (Exception e)+ {+ }+ con = null;+ }+ }+ + public static void restoreOfflineTraders()+ {+ _log.info("Loading offline traders...");+ Connection con = null;+ int nTraders = 0;+ try+ {+ con = L2DatabaseFactory.getInstance().getConnection();+ PreparedStatement stm = con.prepareStatement(LOAD_OFFLINE_STATUS);+ ResultSet rs = stm.executeQuery();+ while (rs.next())+ {+ long time = rs.getLong("time");+ if (Config.OFFLINE_MAX_DAYS > 0)+ {+ Calendar cal = Calendar.getInstance();+ cal.setTimeInMillis(time);+ cal.add(Calendar.DAY_OF_YEAR, Config.OFFLINE_MAX_DAYS);+ if (cal.getTimeInMillis() <= System.currentTimeMillis())+ continue;+ }+ + int type = rs.getInt("type");+ if (type == L2PcInstance.STORE_PRIVATE_NONE)+ continue;+ + L2PcInstance player = null;+ + try+ {+ L2GameClient client = new L2GameClient(null);+ client.setDetached(true);+ player = L2PcInstance.load(rs.getInt("charId"));+ client.setActiveChar(player);+ player.setOnlineStatus(true, false);+ client.setAccountName(player.getAccountName());+ client.setState(GameClientState.IN_GAME);+ player.setClient(client);+ player.setOfflineStartTime(time);+ player.spawnMe(player.getX(), player.getY(), player.getZ());+ LoginServerThread.getInstance().addGameServerLogin(player.getAccountName(), client);+ PreparedStatement stm_items = con.prepareStatement(LOAD_OFFLINE_ITEMS);+ stm_items.setInt(1, player.getObjectId());+ ResultSet items = stm_items.executeQuery();+ + switch (type)+ {+ case L2PcInstance.STORE_PRIVATE_BUY:+ while (items.next())+ {+ if (player.getBuyList().addItemByItemId(items.getInt(2), items.getInt(3), items.getInt(4)) == null)+ throw new NullPointerException();+ }+ player.getBuyList().setTitle(rs.getString("title"));+ break;+ case L2PcInstance.STORE_PRIVATE_SELL:+ case L2PcInstance.STORE_PRIVATE_PACKAGE_SELL:+ while (items.next())+ {+ if (player.getSellList().addItem(items.getInt(2), items.getInt(3), items.getInt(4)) == null)+ throw new NullPointerException();+ }+ player.getSellList().setTitle(rs.getString("title"));+ player.getSellList().setPackaged(type == L2PcInstance.STORE_PRIVATE_PACKAGE_SELL);+ break;+ case L2PcInstance.STORE_PRIVATE_MANUFACTURE:+ L2ManufactureList createList = new L2ManufactureList();+ while (items.next())+ {+ createList.add(new L2ManufactureItem(items.getInt(2), items.getInt(4)));+ }+ player.setCreateList(createList);+ player.getCreateList().setStoreName(rs.getString("title"));+ break;+ }+ items.close();+ stm_items.close();+ + player.sitDown();+ if (Config.OFFLINE_SET_NAME_COLOR)+ player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR);+ player.setPrivateStoreType(type);+ player.setOnlineStatus(true, true);+ player.restoreEffects();+ player.broadcastUserInfo();+ nTraders++;+ }+ catch (Exception e)+ {+ _log.log(Level.WARNING, "OfflineTradersTable[loadOffliners()]: Error loading trader: "+player,e);+ if (player != null)+ {+ player.deleteMe();+ }+ }+ }+ rs.close();+ stm.close();+ _log.info("Loaded: " +nTraders+ " offline trader(s)");+ stm = con.prepareStatement(CLEAR_OFFLINE_TABLE);+ stm.execute();+ stm.close();+ stm = con.prepareStatement(CLEAR_OFFLINE_TABLE_ITEMS);+ stm.execute();+ stm.close();+ }+ catch (Exception e)+ {+ _log.log(Level.WARNING, "OfflineTradersTable[loadOffliners()]: Error while loading offline traders: ",e);+ }+ finally+ {+ try+ {+ con.close();+ }+ catch (Exception e)+ { }+ con = null;+ }+ }+}\ No newline at end of file
CREATE TABLE IF NOT EXISTS `character_offline_trade_items` ( `charId` int(10) unsigned NOT NULL, `item` int(10) unsigned NOT NULL DEFAULT '0', -- itemId(for buy) & ObjectId(for sell) `count` bigint(20) unsigned NOT NULL DEFAULT '0', `price` bigint(20) unsigned NOT NULL DEFAULT '0');CREATE TABLE IF NOT EXISTS `character_offline_trade` ( `charId` int(10) unsigned NOT NULL, `time` bigint(13) unsigned NOT NULL DEFAULT '0', `type` tinyint(4) NOT NULL DEFAULT '0', `title` varchar(50) DEFAULT NULL, PRIMARY KEY (`charId`));
# ================================================================# Offline trade & craft# ================================================================# Enable or disable offline trade mode# Default: FalseOfflineTradeEnable = True# Enable or disable offline craft mode# Default: FalseOfflineCraftEnable = True# Offline name colorOfflineSetNameColor = TrueOfflineNameColor = 808080# Allow fame for characters in offline mode# Default: FalseOfflineFame = True# Restore offline traders/crafters after restart/shutdown.# Default: false.RestoreOffliners = True# Restore offline characters for X days#Default: 10OfflineMaxDays = 10#Disconnect shop after finished selling, buying.#Default: TrueOfflineDisconnectFinished = True