Noticias:

No tienes permiso para ver los enlaces. Para poder verlos Registrate o Conectate.

Menú Principal

Offline Shop Players

Iniciado por Swarlog, Jul 25, 2025, 11:54 PM

Tema anterior - Siguiente tema

Swarlog

CitarCORE:

### Eclipse Workspace Patch 1.0
#P aCis_gameserver
Index: 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 players
Index: 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 file
Index: 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

CitarDATA:

# ================================================================
#                       Offline trade & craft
# ================================================================

# Enable or disable offline trade mode
# Default: False
OfflineTradeEnable = True

# Enable or disable offline craft mode
# Default: False
OfflineCraftEnable = True

# Offline name color
OfflineSetNameColor = True
OfflineNameColor = 808080

# Allow fame for characters in offline mode
# Default: False
OfflineFame = True

# Restore offline traders/crafters after restart/shutdown.
# Default: false.
RestoreOffliners = True

# Restore offline characters for X days
#Default: 10
OfflineMaxDays = 10

#Disconnect shop after finished selling, buying.
#Default: True
OfflineDisconnectFinished = True

CitarSQL:

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`)
);