Помогите создать офлайн торговлю на сборке acis 409 .

rjcnzy008

Путник
Пользователь
Сообщения
21
Розыгрыши
0
Репутация
0
Реакции
1
Баллы
14
Хроники
  1. Interlude
Исходники
Присутствуют
Сборка
aCis_409
может кто подсказать где в каком файле сделать изменения для того чтобы команда .offline заработала . А то я ковыряю уже 3 день . То получается дюп какой то через это команду то оффлайнщики нечего не продают и т.д.(исходники есть) Зарание спасибо
 
Java:
diff --git a/java/net/sf/l2j/Config.java b/java/net/sf/l2j/Config.java
index 4b7181f..68f70b7 100644
--- a/java/net/sf/l2j/Config.java
+++ b/java/net/sf/l2j/Config.java
@@ -35,6 +35,7 @@
    public static final String PLAYERS_FILE = "./config/players.properties";
    public static final String SERVER_FILE = "./config/server.properties";
    public static final String SIEGE_FILE = "./config/siege.properties";
+   public static final String OFFLINEMOD = "./config/CustomMods/OfflineShop.ini";
    
    // --------------------------------------------------
    // Clans settings
@@ -380,7 +381,15 @@
    public static int ENCHANT_MAX_ARMOR;
    public static int ENCHANT_SAFE_MAX;
    public static int ENCHANT_SAFE_MAX_FULL;
-   
+   /** Offline Shop */
+   public static boolean OFFLINE_TRADE_ENABLE;
+   public static boolean OFFLINE_CRAFT_ENABLE;
+   public static boolean OFFLINE_MODE_IN_PEACE_ZONE;
+   public static boolean OFFLINE_MODE_NO_DAMAGE;
+   public static boolean RESTORE_OFFLINERS;
+   public static int OFFLINE_MAX_DAYS;
+   public static boolean OFFLINE_DISCONNECT_FINISHED;
+   public static boolean OFFLINE_SET_SLEEP;
    /** Augmentations */
    public static int AUGMENTATION_NG_SKILL_CHANCE;
    public static int AUGMENTATION_NG_GLOW_CHANCE;
@@ -1088,6 +1097,19 @@
        STORE_SKILL_COOLTIME = players.getProperty("StoreSkillCooltime", true);
    }
    
+   private static final void loadOff()
+   {
+       final ExProperties offlineshop = initProperties(Config.OFFLINEMOD);
+       OFFLINE_TRADE_ENABLE = offlineshop.getProperty("OfflineTradeEnable", false);
+       OFFLINE_CRAFT_ENABLE = offlineshop.getProperty("OfflineCraftEnable", false);
+       OFFLINE_MODE_IN_PEACE_ZONE = offlineshop.getProperty("OfflineModeInPeaceZone", false);
+       OFFLINE_MODE_NO_DAMAGE = offlineshop.getProperty("OfflineModeNoDamage", false);
+       OFFLINE_SET_SLEEP = offlineshop.getProperty("OfflineSetSleepEffect", false);
+       RESTORE_OFFLINERS = offlineshop.getProperty("RestoreOffliners", false);
+       OFFLINE_MAX_DAYS = offlineshop.getProperty("OfflineMaxDays", 10);
+       OFFLINE_DISCONNECT_FINISHED = offlineshop.getProperty("OfflineDisconnectFinished", true);
+   
+   }
    /**
     * Loads siege settings.
     */
@@ -1307,6 +1329,9 @@
        // siege settings
        loadSieges();
        
+       // OffShop settings
+       loadOff();
+       
        // server settings
        loadServer();
    }
diff --git a/java/net/sf/l2j/gameserver/GameServer.java b/java/net/sf/l2j/gameserver/GameServer.java
index 41a9f92..402a66a 100644
--- a/java/net/sf/l2j/gameserver/GameServer.java
+++ b/java/net/sf/l2j/gameserver/GameServer.java
@@ -71,6 +71,7 @@
 import net.sf.l2j.gameserver.data.xml.SummonItemData;
 import net.sf.l2j.gameserver.data.xml.TeleportLocationData;
 import net.sf.l2j.gameserver.data.xml.WalkerRouteData;
+import net.sf.l2j.gameserver.enums.actors.OfflineStoresData;
 import net.sf.l2j.gameserver.geoengine.GeoEngine;
 import net.sf.l2j.gameserver.handler.AdminCommandHandler;
 import net.sf.l2j.gameserver.handler.ChatHandler;
@@ -243,6 +244,10 @@
        Olympiad.getInstance();
        HeroManager.getInstance();
        
+       StringUtil.printSection("OfflineShop Started");
+       if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)
+       OfflineStoresData.getInstance().restoreOfflineTraders();
+       
        StringUtil.printSection("Four Sepulchers");
        FourSepulchersManager.getInstance();
        
diff --git a/java/net/sf/l2j/gameserver/LoginServerThread.java b/java/net/sf/l2j/gameserver/LoginServerThread.java
index 477d0af..0eb4fd2 100644
--- a/java/net/sf/l2j/gameserver/LoginServerThread.java
+++ b/java/net/sf/l2j/gameserver/LoginServerThread.java
@@ -295,6 +295,8 @@
    public void addClient(String account, GameClient client)
    {
        final GameClient existingClient = _clients.putIfAbsent(account, client);
+       if (client.isDetached())
+           return;
        if (existingClient == null)
        {
            try
diff --git a/java/net/sf/l2j/gameserver/Shutdown.java b/java/net/sf/l2j/gameserver/Shutdown.java
index 88a3dc4..f90b31e 100644
--- a/java/net/sf/l2j/gameserver/Shutdown.java
+++ b/java/net/sf/l2j/gameserver/Shutdown.java
@@ -18,6 +18,7 @@
 import net.sf.l2j.gameserver.data.manager.SevenSignsManager;
 import net.sf.l2j.gameserver.data.manager.ZoneManager;
 import net.sf.l2j.gameserver.data.sql.ServerMemoTable;
+import net.sf.l2j.gameserver.enums.actors.OfflineStoresData;
 import net.sf.l2j.gameserver.model.World;
 import net.sf.l2j.gameserver.model.actor.Player;
 import net.sf.l2j.gameserver.model.olympiad.Olympiad;
@@ -77,7 +78,18 @@
        if (this == SingletonHolder.INSTANCE)
        {
            StringUtil.printSection("Under " + MODE_TEXT[_shutdownMode] + " process");
-           
+           try
+           {
+               if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)
+               {
+                   OfflineStoresData.getInstance().storeOffliners();
+                   LOGGER.info("Offline Traders Table: Offline shops stored.");
+               }
+           }
+           catch (Throwable t)
+           {
+               
+           }
            // disconnect players
            try
            {
diff --git a/java/net/sf/l2j/gameserver/enums/actors/OfflineStoresData.java b/java/net/sf/l2j/gameserver/enums/actors/OfflineStoresData.java
new file mode 100644
index 0000000..47a48b3
--- /dev/null
+++ b/java/net/sf/l2j/gameserver/enums/actors/OfflineStoresData.java
@@ -0,0 +1,276 @@
+package net.sf.l2j.gameserver.enums.actors;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+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.enums.ZoneId;
+import net.sf.l2j.gameserver.model.World;
+import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.craft.ManufactureItem;
+import net.sf.l2j.gameserver.model.craft.ManufactureList;
+import net.sf.l2j.gameserver.model.tradelist.TradeItem;
+import net.sf.l2j.gameserver.network.GameClient;
+import net.sf.l2j.gameserver.network.GameClient.GameClientState;
+
+public class OfflineStoresData
+{
+   private static final Logger LOGGER = Logger.getLogger(OfflineStoresData.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`,`enchant`) 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 void storeOffliners()
+   {
+       try (Connection con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement save_offline_status = con.prepareStatement(SAVE_OFFLINE_STATUS); PreparedStatement save_items = con.prepareStatement(SAVE_ITEMS))
+       {
+           try (Statement stm = con.createStatement())
+           {
+               stm.execute(CLEAR_OFFLINE_TABLE);
+               stm.execute(CLEAR_OFFLINE_TABLE_ITEMS);
+           }
+           for (Player pc : World.getInstance().getPlayers())
+           {
+               try
+               {
+                   if (pc.getStoreType() != StoreType.NONE && (pc.getClient() == null || pc.getClient().isDetached()))
+                   {
+                       save_offline_status.setInt(1, pc.getObjectId());
+                       save_offline_status.setLong(2, pc.getOfflineStartTime());
+                       save_offline_status.setInt(3, pc.getStoreType().getId());
+                       switch (pc.getStoreType())
+                       {
+                           case BUY:
+                               if (!Config.OFFLINE_TRADE_ENABLE)
+                                   continue;
+
+                               save_offline_status.setString(4, pc.getBuyList().getTitle());
+                               for (TradeItem i : pc.getBuyList().getItems())
+                               {
+                                   save_items.setInt(1, pc.getObjectId());
+                                   save_items.setInt(2, i.getItem().getItemId());
+                                   save_items.setLong(3, i.getCount());
+                                   save_items.setLong(4, i.getPrice());
+                                   save_items.setLong(5, i.getEnchant());
+                                   save_items.addBatch();
+                               }
+                               break;
+                           case SELL:
+                           case PACKAGE_SELL:
+                               if (!Config.OFFLINE_TRADE_ENABLE)
+                                   continue;
+
+                               save_offline_status.setString(4, pc.getSellList().getTitle());
+                               pc.getSellList().updateItems();
+                               for (TradeItem i : pc.getSellList().getItems())
+                               {
+                                   save_items.setInt(1, pc.getObjectId());
+                                   save_items.setInt(2, i.getObjectId());
+                                   save_items.setLong(3, i.getCount());
+                                   save_items.setLong(4, i.getPrice());
+                                   save_items.setLong(5, i.getEnchant());
+                                   save_items.addBatch();
+                               }
+                               break;
+                           case MANUFACTURE:
+                               if (!Config.OFFLINE_CRAFT_ENABLE)
+                                   continue;
+
+                               save_offline_status.setString(4, pc.getCreateList().getStoreName());
+                               for (ManufactureItem i : pc.getCreateList().getList())
+                               {
+                                   save_items.setInt(1, pc.getObjectId());
+                                   save_items.setInt(2, i.getId());
+                                   save_items.setLong(3, 0L);
+                                   save_items.setLong(4, i.getValue());
+                                   save_items.setLong(5, 0L);
+                                   save_items.addBatch();
+                               }
+                               break;
+                       }
+                       save_items.executeBatch();
+                       save_offline_status.execute();
+                   }
+               }
+               catch (Exception e)
+               {
+                   LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while saving offline trader: " + pc.getObjectId() + " " + e, e);
+               }
+           }
+
+           LOGGER.info(getClass().getSimpleName() + ": Offline traders stored.");
+       }
+       catch (Exception e)
+       {
+           LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while saving offline traders: " + e, e);
+       }
+   }
+
+   public void restoreOfflineTraders()
+   {
+       LOGGER.info(getClass().getSimpleName() + ": Loading offline traders...");
+       try (Connection con = L2DatabaseFactory.getInstance().getConnection(); Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery(LOAD_OFFLINE_STATUS))
+       {
+           int nTraders = 0;
+           while (rs.next())
+           {
+               final long time = rs.getLong("time");
+               if (Config.OFFLINE_MAX_DAYS > 0)
+               {
+                   final Calendar cal = Calendar.getInstance();
+                   cal.setTimeInMillis(time);
+                   cal.add(Calendar.DAY_OF_YEAR, Config.OFFLINE_MAX_DAYS);
+                   if (cal.getTimeInMillis() <= System.currentTimeMillis())
+                       continue;
+               }
+
+               StoreType type = null;
+               for (StoreType t : StoreType.values())
+               {
+                   if (t.getId() == rs.getInt("type"))
+                   {
+                       type = t;
+                       break;
+                   }
+               }
+               if (type == null)
+               {
+                   LOGGER.warning(getClass().getSimpleName() + ": PrivateStoreType with id " + rs.getInt("type") + " could not be found.");
+                   continue;
+               }
+               if (type == StoreType.NONE)
+                   continue;
+
+               final Player player = Player.restore(rs.getInt("charId"));
+               if (player == null)
+                   continue;
+
+               try (PreparedStatement stm_items = con.prepareStatement(LOAD_OFFLINE_ITEMS))
+               {
+                   player.isRunning();
+                   player.sitDown();
+                   player.setOnlineStatus(true, false);
+
+                   World.getInstance().addPlayer(player);
+
+                   final GameClient client = new GameClient(null);
+                   client.setDetached(true);
+                   player.setClient(client);
+                   client.setPlayer(player);
+                   client.setAccountName(player.getAccountNamePlayer());
+                   player.setOnlineStatus(true, true);
+                   client.setState(GameClientState.IN_GAME);
+                   player.setOfflineStartTime(time);
+                   player.spawnMe();
+
+                   LoginServerThread.getInstance().addClient(player.getAccountName(), client);
+
+                   stm_items.setInt(1, player.getObjectId());
+                   try (ResultSet items = stm_items.executeQuery())
+                   {
+                       switch (type)
+                       {
+                           case BUY:
+                               while (items.next())
+                               {
+                               player.getBuyList().addItemByItemId(items.getInt(2), items.getInt(3), items.getInt(4));
+                               }
+                               
+                               player.getBuyList().setTitle(rs.getString("title"));
+                               break;
+                           case SELL:
+                           case PACKAGE_SELL:
+                               while (items.next())
+                                   if (player.getSellList().addItem(items.getInt(2), items.getInt(3), items.getInt(4)) == null)
+                                       throw new NullPointerException("NPE at SELL of offlineShop " + player.getObjectId() + " " + items.getInt(2) + " " + items.getInt(3) + " " + items.getInt(4));
+                               
+                               player.getSellList().setTitle(rs.getString("title"));
+                               player.getSellList().setPackaged(type == StoreType.PACKAGE_SELL);
+                               break;
+                           case MANUFACTURE:
+                               final ManufactureList createList = new ManufactureList();
+                               createList.setStoreName(rs.getString("title"));
+                               while (items.next())
+                               createList.add(new ManufactureItem(items.getInt(2), items.getInt(4)));
+                               //player.setCreateList(createList);
+                               break;
+                       }
+                   }
+
+                   if (Config.OFFLINE_SET_SLEEP)
+                       player.startAbnormalEffect(0x000080);
+
+                   player.setStoreType(type);
+                   player.restoreEffects();
+                   player.broadcastUserInfo();
+
+                   nTraders++;
+               }
+               catch (Exception e)
+               {
+                   LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e);
+
+                   player.deleteMe();
+               }
+           }
+
+           LOGGER.info(getClass().getSimpleName() + ": Loaded: " + nTraders + " offline trader(s)");
+
+           try (Statement stm1 = con.createStatement())
+           {
+               stm1.execute(CLEAR_OFFLINE_TABLE);
+               stm1.execute(CLEAR_OFFLINE_TABLE_ITEMS);
+           }
+       }
+       catch (Exception e)
+       {
+           LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while loading offline traders: ", e);
+       }
+   }
+
+   public static boolean offlineMode(Player player)
+   {
+       if (player.isInOlympiadMode() || player.isFestivalParticipant() || player.isInJail() || player.getBoat() != null)
+           return false;
+
+       boolean canSetShop = false;
+       switch (player.getStoreType())
+       {
+           case SELL:
+           case PACKAGE_SELL:
+           case BUY:
+               canSetShop = Config.OFFLINE_TRADE_ENABLE;
+               break;
+           case MANUFACTURE:
+               canSetShop = Config.OFFLINE_CRAFT_ENABLE;
+               break;
+       }
+       if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE))
+           canSetShop = false;
+
+       return canSetShop;
+   }
+
+   public static OfflineStoresData getInstance()
+   {
+       return SingletonHolder._instance;
+   }
+
+   private static class SingletonHolder
+   {
+       protected static final OfflineStoresData _instance = new OfflineStoresData();
+   }
+}
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/enums/actors/StoreType.java b/java/net/sf/l2j/gameserver/enums/actors/StoreType.java
index b7da1c6..dca591f 100644
--- a/java/net/sf/l2j/gameserver/enums/actors/StoreType.java
+++ b/java/net/sf/l2j/gameserver/enums/actors/StoreType.java
@@ -21,4 +21,13 @@
    {
        return _id;
    }
+   public static StoreType findById(int id)
+   {
+   for (StoreType privateStoreType : values())
+   {
+   if (privateStoreType.getId() == id)
+   return privateStoreType;
+   }
+   return null;
+   }
 }
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/model/actor/Player.java b/java/net/sf/l2j/gameserver/model/actor/Player.java
index 9436ef0..dad3cc4 100644
--- a/java/net/sf/l2j/gameserver/model/actor/Player.java
+++ b/java/net/sf/l2j/gameserver/model/actor/Player.java
@@ -2607,9 +2607,14 @@
    
    public String getAccountName()
    {
+       if (getClient() == null)
+       return getAccountNamePlayer();
        return _accountName;
    }
-   
+   public String getAccountNamePlayer()
+   {
+   return _accountName;
+   }
    public Map<Integer, String> getAccountChars()
    {
        return _chars;
@@ -4113,6 +4118,8 @@
    public void setStoreType(StoreType type)
    {
        _storeType = type;
+       if (Config.OFFLINE_DISCONNECT_FINISHED && type == StoreType.NONE && (getClient() == null || getClient().isDetached()))
+           deleteMe();
    }
    
    /**
@@ -4122,7 +4129,16 @@
    {
        return _storeType;
    }
+   private long _offlineShopStart;
+   public long getOfflineStartTime()
+   {
+       return _offlineShopStart;
+   }
    
+   public void setOfflineStartTime(long time)
+   {
+       _offlineShopStart = time;
+   }
    /**
     * @return true if the {@link Player} can use dwarven recipes.
     */
diff --git a/java/net/sf/l2j/gameserver/network/GameClient.java b/java/net/sf/l2j/gameserver/network/GameClient.java
index 5218e60..823728e 100644
--- a/java/net/sf/l2j/gameserver/network/GameClient.java
+++ b/java/net/sf/l2j/gameserver/network/GameClient.java
@@ -21,9 +21,12 @@
 import net.sf.l2j.gameserver.LoginServerThread;
 import net.sf.l2j.gameserver.data.sql.ClanTable;
 import net.sf.l2j.gameserver.data.sql.PlayerInfoTable;
+import net.sf.l2j.gameserver.enums.MessageType;
+import net.sf.l2j.gameserver.enums.ZoneId;
 import net.sf.l2j.gameserver.model.CharSelectSlot;
 import net.sf.l2j.gameserver.model.World;
 import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.olympiad.OlympiadManager;
 import net.sf.l2j.gameserver.model.pledge.Clan;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket;
@@ -208,6 +211,29 @@
                if (getPlayer() != null && !isDetached())
                {
                    setDetached(true);
+                   if (offlineMode(getPlayer()))
+                   {
+                       if (getPlayer().getParty() != null)
+                           getPlayer().getParty().removePartyMember(getPlayer(), MessageType.EXPELLED);
+                       OlympiadManager.getInstance().unRegisterNoble(getPlayer());
+                       
+                       // If the Character has Pet, unsummon it
+                       if (getPlayer().hasPet())
+                       {
+                           getPlayer().getSummon().unSummon(getPlayer());
+                           // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline)
+                           if (getPlayer().getSummon() != null)
+                               getPlayer().getSummon().updateAndBroadcastStatus(0);
+                       }
+                       
+                       if (Config.OFFLINE_SET_SLEEP)
+                           getPlayer().startAbnormalEffect(0x000080);
+                       
+                       if (getPlayer().getOfflineStartTime() == 0)
+                           getPlayer().setOfflineStartTime(System.currentTimeMillis());
+                       
+                       return;
+                   }
                    fast = !getPlayer().isInCombat() && !getPlayer().isLocked();
                }
                cleanMe(fast);
@@ -218,6 +244,44 @@
        }
    }
    
+   /**
+    * @param player the player to be check.
+    * @return {@code true} if the player is allowed to remain as off-line shop.
+    */
+   public static boolean offlineMode(Player player)
+   {
+       if (player.isInOlympiadMode() || player.isFestivalParticipant() || player.isInJail() || player.getBoat() != null)
+           return false;
+       
+       boolean canSetShop = false;
+       switch (player.getStoreType())
+       {
+           case SELL:
+           case PACKAGE_SELL:
+           case BUY:
+           {
+               canSetShop = Config.OFFLINE_TRADE_ENABLE;
+               break;
+           }
+           case MANUFACTURE:
+           {
+               canSetShop = Config.OFFLINE_TRADE_ENABLE;
+               break;
+           }
+           default:
+           {
+               canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isCrafting();
+               break;
+           }
+       }
+       
+       if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE))
+           canSetShop = false;
+       
+       return canSetShop;
+   }
+
+
    @Override
    protected void onForcedDisconnection()
    {
@@ -580,6 +644,8 @@
    
    public void close(L2GameServerPacket gsp)
    {
+       if (getConnection() == null)
+       return;
        getConnection().close(gsp);
    }
    
 
Criar Tabela SQL
 
+character_offline_trade_items
+CREATE TABLE IF NOT EXISTS `character_offline_trade_items` (
+  `charId` int(10) NOT NULL DEFAULT 0,
+  `item` int(10) NOT NULL DEFAULT 0,
+  `count` int(20) NOT NULL DEFAULT 0,
+  `price` int(20) NOT NULL DEFAULT 0,
+  `enchant` int(20) NOT NULL DEFAULT 0
+);
 
+character_offline_trade
+CREATE TABLE IF NOT EXISTS `character_offline_trade` (
+  `charId` int(11) NOT NULL,
+  `time` bigint(20) unsigned NOT NULL DEFAULT 0,
+  `type` tinyint(4) NOT NULL DEFAULT 0,
+  `title` varchar(100) DEFAULT NULL,
+  PRIMARY KEY (`charId`)
+);
 
TOOLS
database_installer.bat
%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_memo.sql
+%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_offline_trade.sql
+%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_offline_trade_items.sql
%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_quests.sql
 
database_installer.sh
$MYG < ../sql/character_memo.sql &> /dev/null
+$MYG < ../sql/character_offline_trade.sql &> /dev/null
+$MYG < ../sql/character_offline_trade_items.sql &> /dev/null
$MYG < ../sql/character_quests.sql &> /dev/null
 
full_instal.sql
DROP TABLE IF EXISTS character_memo;
+DROP TABLE IF EXISTS character_offline_trade;
+DROP TABLE IF EXISTS character_offline_trade_items;
DROP TABLE IF EXISTS character_quests;
 
 
Index: DataPack
 
+# =================================================================
+#                       Offline trade/craft
+# =================================================================
+
+# Option to enable or disable offline trade feature.
+# Enable -> true, Disable -> false
+OfflineTradeEnable = True
+
+# Option to enable or disable offline craft feature.
+# Enable -> true, Disable -> false
+OfflineCraftEnable = True
+
+# If set to True, off-line shops will be possible only in peace zones.
+# Default: False
+OfflineModeInPeaceZone = True
+
+# If set to True, players in off-line shop mode will not take any damage, thus they cannot be killed.
+# Default: False
+OfflineModeNoDamage = False
+
+# Restore offline traders/crafters after restart/shutdown.
+# Default: False
+RestoreOffliners = True
+
+# Do not restore offline characters, after OfflineMaxDays days spent from first restore.
+# Require server restart to disconnect expired shops.
+# 0 = disabled (always restore).
+# Default: 7
+OfflineMaxDays = 7
+
+# Disconnect shop after finished selling, buying.
+# Default: True
+OfflineDisconnectFinished = True
+
+#Offline Effect Sleep
+OfflineSetSleepEffect = True

Под более раннюю версию, но в должно сработать и у тебя, если импорты под 409 поменять
 
Java:
diff --git a/java/net/sf/l2j/Config.java b/java/net/sf/l2j/Config.java
index 4b7181f..68f70b7 100644
--- a/java/net/sf/l2j/Config.java
+++ b/java/net/sf/l2j/Config.java
@@ -35,6 +35,7 @@
    public static final String PLAYERS_FILE = "./config/players.properties";
    public static final String SERVER_FILE = "./config/server.properties";
    public static final String SIEGE_FILE = "./config/siege.properties";
+   public static final String OFFLINEMOD = "./config/CustomMods/OfflineShop.ini";
   
    // --------------------------------------------------
    // Clans settings
@@ -380,7 +381,15 @@
    public static int ENCHANT_MAX_ARMOR;
    public static int ENCHANT_SAFE_MAX;
    public static int ENCHANT_SAFE_MAX_FULL;
-  
+   /** Offline Shop */
+   public static boolean OFFLINE_TRADE_ENABLE;
+   public static boolean OFFLINE_CRAFT_ENABLE;
+   public static boolean OFFLINE_MODE_IN_PEACE_ZONE;
+   public static boolean OFFLINE_MODE_NO_DAMAGE;
+   public static boolean RESTORE_OFFLINERS;
+   public static int OFFLINE_MAX_DAYS;
+   public static boolean OFFLINE_DISCONNECT_FINISHED;
+   public static boolean OFFLINE_SET_SLEEP;
    /** Augmentations */
    public static int AUGMENTATION_NG_SKILL_CHANCE;
    public static int AUGMENTATION_NG_GLOW_CHANCE;
@@ -1088,6 +1097,19 @@
        STORE_SKILL_COOLTIME = players.getProperty("StoreSkillCooltime", true);
    }
   
+   private static final void loadOff()
+   {
+       final ExProperties offlineshop = initProperties(Config.OFFLINEMOD);
+       OFFLINE_TRADE_ENABLE = offlineshop.getProperty("OfflineTradeEnable", false);
+       OFFLINE_CRAFT_ENABLE = offlineshop.getProperty("OfflineCraftEnable", false);
+       OFFLINE_MODE_IN_PEACE_ZONE = offlineshop.getProperty("OfflineModeInPeaceZone", false);
+       OFFLINE_MODE_NO_DAMAGE = offlineshop.getProperty("OfflineModeNoDamage", false);
+       OFFLINE_SET_SLEEP = offlineshop.getProperty("OfflineSetSleepEffect", false);
+       RESTORE_OFFLINERS = offlineshop.getProperty("RestoreOffliners", false);
+       OFFLINE_MAX_DAYS = offlineshop.getProperty("OfflineMaxDays", 10);
+       OFFLINE_DISCONNECT_FINISHED = offlineshop.getProperty("OfflineDisconnectFinished", true);
+  
+   }
    /**
     * Loads siege settings.
     */
@@ -1307,6 +1329,9 @@
        // siege settings
        loadSieges();
       
+       // OffShop settings
+       loadOff();
+      
        // server settings
        loadServer();
    }
diff --git a/java/net/sf/l2j/gameserver/GameServer.java b/java/net/sf/l2j/gameserver/GameServer.java
index 41a9f92..402a66a 100644
--- a/java/net/sf/l2j/gameserver/GameServer.java
+++ b/java/net/sf/l2j/gameserver/GameServer.java
@@ -71,6 +71,7 @@
 import net.sf.l2j.gameserver.data.xml.SummonItemData;
 import net.sf.l2j.gameserver.data.xml.TeleportLocationData;
 import net.sf.l2j.gameserver.data.xml.WalkerRouteData;
+import net.sf.l2j.gameserver.enums.actors.OfflineStoresData;
 import net.sf.l2j.gameserver.geoengine.GeoEngine;
 import net.sf.l2j.gameserver.handler.AdminCommandHandler;
 import net.sf.l2j.gameserver.handler.ChatHandler;
@@ -243,6 +244,10 @@
        Olympiad.getInstance();
        HeroManager.getInstance();
       
+       StringUtil.printSection("OfflineShop Started");
+       if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)
+       OfflineStoresData.getInstance().restoreOfflineTraders();
+      
        StringUtil.printSection("Four Sepulchers");
        FourSepulchersManager.getInstance();
       
diff --git a/java/net/sf/l2j/gameserver/LoginServerThread.java b/java/net/sf/l2j/gameserver/LoginServerThread.java
index 477d0af..0eb4fd2 100644
--- a/java/net/sf/l2j/gameserver/LoginServerThread.java
+++ b/java/net/sf/l2j/gameserver/LoginServerThread.java
@@ -295,6 +295,8 @@
    public void addClient(String account, GameClient client)
    {
        final GameClient existingClient = _clients.putIfAbsent(account, client);
+       if (client.isDetached())
+           return;
        if (existingClient == null)
        {
            try
diff --git a/java/net/sf/l2j/gameserver/Shutdown.java b/java/net/sf/l2j/gameserver/Shutdown.java
index 88a3dc4..f90b31e 100644
--- a/java/net/sf/l2j/gameserver/Shutdown.java
+++ b/java/net/sf/l2j/gameserver/Shutdown.java
@@ -18,6 +18,7 @@
 import net.sf.l2j.gameserver.data.manager.SevenSignsManager;
 import net.sf.l2j.gameserver.data.manager.ZoneManager;
 import net.sf.l2j.gameserver.data.sql.ServerMemoTable;
+import net.sf.l2j.gameserver.enums.actors.OfflineStoresData;
 import net.sf.l2j.gameserver.model.World;
 import net.sf.l2j.gameserver.model.actor.Player;
 import net.sf.l2j.gameserver.model.olympiad.Olympiad;
@@ -77,7 +78,18 @@
        if (this == SingletonHolder.INSTANCE)
        {
            StringUtil.printSection("Under " + MODE_TEXT[_shutdownMode] + " process");
-          
+           try
+           {
+               if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)
+               {
+                   OfflineStoresData.getInstance().storeOffliners();
+                   LOGGER.info("Offline Traders Table: Offline shops stored.");
+               }
+           }
+           catch (Throwable t)
+           {
+              
+           }
            // disconnect players
            try
            {
diff --git a/java/net/sf/l2j/gameserver/enums/actors/OfflineStoresData.java b/java/net/sf/l2j/gameserver/enums/actors/OfflineStoresData.java
new file mode 100644
index 0000000..47a48b3
--- /dev/null
+++ b/java/net/sf/l2j/gameserver/enums/actors/OfflineStoresData.java
@@ -0,0 +1,276 @@
+package net.sf.l2j.gameserver.enums.actors;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+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.enums.ZoneId;
+import net.sf.l2j.gameserver.model.World;
+import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.craft.ManufactureItem;
+import net.sf.l2j.gameserver.model.craft.ManufactureList;
+import net.sf.l2j.gameserver.model.tradelist.TradeItem;
+import net.sf.l2j.gameserver.network.GameClient;
+import net.sf.l2j.gameserver.network.GameClient.GameClientState;
+
+public class OfflineStoresData
+{
+   private static final Logger LOGGER = Logger.getLogger(OfflineStoresData.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`,`enchant`) 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 void storeOffliners()
+   {
+       try (Connection con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement save_offline_status = con.prepareStatement(SAVE_OFFLINE_STATUS); PreparedStatement save_items = con.prepareStatement(SAVE_ITEMS))
+       {
+           try (Statement stm = con.createStatement())
+           {
+               stm.execute(CLEAR_OFFLINE_TABLE);
+               stm.execute(CLEAR_OFFLINE_TABLE_ITEMS);
+           }
+           for (Player pc : World.getInstance().getPlayers())
+           {
+               try
+               {
+                   if (pc.getStoreType() != StoreType.NONE && (pc.getClient() == null || pc.getClient().isDetached()))
+                   {
+                       save_offline_status.setInt(1, pc.getObjectId());
+                       save_offline_status.setLong(2, pc.getOfflineStartTime());
+                       save_offline_status.setInt(3, pc.getStoreType().getId());
+                       switch (pc.getStoreType())
+                       {
+                           case BUY:
+                               if (!Config.OFFLINE_TRADE_ENABLE)
+                                   continue;
+
+                               save_offline_status.setString(4, pc.getBuyList().getTitle());
+                               for (TradeItem i : pc.getBuyList().getItems())
+                               {
+                                   save_items.setInt(1, pc.getObjectId());
+                                   save_items.setInt(2, i.getItem().getItemId());
+                                   save_items.setLong(3, i.getCount());
+                                   save_items.setLong(4, i.getPrice());
+                                   save_items.setLong(5, i.getEnchant());
+                                   save_items.addBatch();
+                               }
+                               break;
+                           case SELL:
+                           case PACKAGE_SELL:
+                               if (!Config.OFFLINE_TRADE_ENABLE)
+                                   continue;
+
+                               save_offline_status.setString(4, pc.getSellList().getTitle());
+                               pc.getSellList().updateItems();
+                               for (TradeItem i : pc.getSellList().getItems())
+                               {
+                                   save_items.setInt(1, pc.getObjectId());
+                                   save_items.setInt(2, i.getObjectId());
+                                   save_items.setLong(3, i.getCount());
+                                   save_items.setLong(4, i.getPrice());
+                                   save_items.setLong(5, i.getEnchant());
+                                   save_items.addBatch();
+                               }
+                               break;
+                           case MANUFACTURE:
+                               if (!Config.OFFLINE_CRAFT_ENABLE)
+                                   continue;
+
+                               save_offline_status.setString(4, pc.getCreateList().getStoreName());
+                               for (ManufactureItem i : pc.getCreateList().getList())
+                               {
+                                   save_items.setInt(1, pc.getObjectId());
+                                   save_items.setInt(2, i.getId());
+                                   save_items.setLong(3, 0L);
+                                   save_items.setLong(4, i.getValue());
+                                   save_items.setLong(5, 0L);
+                                   save_items.addBatch();
+                               }
+                               break;
+                       }
+                       save_items.executeBatch();
+                       save_offline_status.execute();
+                   }
+               }
+               catch (Exception e)
+               {
+                   LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while saving offline trader: " + pc.getObjectId() + " " + e, e);
+               }
+           }
+
+           LOGGER.info(getClass().getSimpleName() + ": Offline traders stored.");
+       }
+       catch (Exception e)
+       {
+           LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while saving offline traders: " + e, e);
+       }
+   }
+
+   public void restoreOfflineTraders()
+   {
+       LOGGER.info(getClass().getSimpleName() + ": Loading offline traders...");
+       try (Connection con = L2DatabaseFactory.getInstance().getConnection(); Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery(LOAD_OFFLINE_STATUS))
+       {
+           int nTraders = 0;
+           while (rs.next())
+           {
+               final long time = rs.getLong("time");
+               if (Config.OFFLINE_MAX_DAYS > 0)
+               {
+                   final Calendar cal = Calendar.getInstance();
+                   cal.setTimeInMillis(time);
+                   cal.add(Calendar.DAY_OF_YEAR, Config.OFFLINE_MAX_DAYS);
+                   if (cal.getTimeInMillis() <= System.currentTimeMillis())
+                       continue;
+               }
+
+               StoreType type = null;
+               for (StoreType t : StoreType.values())
+               {
+                   if (t.getId() == rs.getInt("type"))
+                   {
+                       type = t;
+                       break;
+                   }
+               }
+               if (type == null)
+               {
+                   LOGGER.warning(getClass().getSimpleName() + ": PrivateStoreType with id " + rs.getInt("type") + " could not be found.");
+                   continue;
+               }
+               if (type == StoreType.NONE)
+                   continue;
+
+               final Player player = Player.restore(rs.getInt("charId"));
+               if (player == null)
+                   continue;
+
+               try (PreparedStatement stm_items = con.prepareStatement(LOAD_OFFLINE_ITEMS))
+               {
+                   player.isRunning();
+                   player.sitDown();
+                   player.setOnlineStatus(true, false);
+
+                   World.getInstance().addPlayer(player);
+
+                   final GameClient client = new GameClient(null);
+                   client.setDetached(true);
+                   player.setClient(client);
+                   client.setPlayer(player);
+                   client.setAccountName(player.getAccountNamePlayer());
+                   player.setOnlineStatus(true, true);
+                   client.setState(GameClientState.IN_GAME);
+                   player.setOfflineStartTime(time);
+                   player.spawnMe();
+
+                   LoginServerThread.getInstance().addClient(player.getAccountName(), client);
+
+                   stm_items.setInt(1, player.getObjectId());
+                   try (ResultSet items = stm_items.executeQuery())
+                   {
+                       switch (type)
+                       {
+                           case BUY:
+                               while (items.next())
+                               {
+                               player.getBuyList().addItemByItemId(items.getInt(2), items.getInt(3), items.getInt(4));
+                               }
+                              
+                               player.getBuyList().setTitle(rs.getString("title"));
+                               break;
+                           case SELL:
+                           case PACKAGE_SELL:
+                               while (items.next())
+                                   if (player.getSellList().addItem(items.getInt(2), items.getInt(3), items.getInt(4)) == null)
+                                       throw new NullPointerException("NPE at SELL of offlineShop " + player.getObjectId() + " " + items.getInt(2) + " " + items.getInt(3) + " " + items.getInt(4));
+                              
+                               player.getSellList().setTitle(rs.getString("title"));
+                               player.getSellList().setPackaged(type == StoreType.PACKAGE_SELL);
+                               break;
+                           case MANUFACTURE:
+                               final ManufactureList createList = new ManufactureList();
+                               createList.setStoreName(rs.getString("title"));
+                               while (items.next())
+                               createList.add(new ManufactureItem(items.getInt(2), items.getInt(4)));
+                               //player.setCreateList(createList);
+                               break;
+                       }
+                   }
+
+                   if (Config.OFFLINE_SET_SLEEP)
+                       player.startAbnormalEffect(0x000080);
+
+                   player.setStoreType(type);
+                   player.restoreEffects();
+                   player.broadcastUserInfo();
+
+                   nTraders++;
+               }
+               catch (Exception e)
+               {
+                   LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e);
+
+                   player.deleteMe();
+               }
+           }
+
+           LOGGER.info(getClass().getSimpleName() + ": Loaded: " + nTraders + " offline trader(s)");
+
+           try (Statement stm1 = con.createStatement())
+           {
+               stm1.execute(CLEAR_OFFLINE_TABLE);
+               stm1.execute(CLEAR_OFFLINE_TABLE_ITEMS);
+           }
+       }
+       catch (Exception e)
+       {
+           LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while loading offline traders: ", e);
+       }
+   }
+
+   public static boolean offlineMode(Player player)
+   {
+       if (player.isInOlympiadMode() || player.isFestivalParticipant() || player.isInJail() || player.getBoat() != null)
+           return false;
+
+       boolean canSetShop = false;
+       switch (player.getStoreType())
+       {
+           case SELL:
+           case PACKAGE_SELL:
+           case BUY:
+               canSetShop = Config.OFFLINE_TRADE_ENABLE;
+               break;
+           case MANUFACTURE:
+               canSetShop = Config.OFFLINE_CRAFT_ENABLE;
+               break;
+       }
+       if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE))
+           canSetShop = false;
+
+       return canSetShop;
+   }
+
+   public static OfflineStoresData getInstance()
+   {
+       return SingletonHolder._instance;
+   }
+
+   private static class SingletonHolder
+   {
+       protected static final OfflineStoresData _instance = new OfflineStoresData();
+   }
+}
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/enums/actors/StoreType.java b/java/net/sf/l2j/gameserver/enums/actors/StoreType.java
index b7da1c6..dca591f 100644
--- a/java/net/sf/l2j/gameserver/enums/actors/StoreType.java
+++ b/java/net/sf/l2j/gameserver/enums/actors/StoreType.java
@@ -21,4 +21,13 @@
    {
        return _id;
    }
+   public static StoreType findById(int id)
+   {
+   for (StoreType privateStoreType : values())
+   {
+   if (privateStoreType.getId() == id)
+   return privateStoreType;
+   }
+   return null;
+   }
 }
\ No newline at end of file
diff --git a/java/net/sf/l2j/gameserver/model/actor/Player.java b/java/net/sf/l2j/gameserver/model/actor/Player.java
index 9436ef0..dad3cc4 100644
--- a/java/net/sf/l2j/gameserver/model/actor/Player.java
+++ b/java/net/sf/l2j/gameserver/model/actor/Player.java
@@ -2607,9 +2607,14 @@
   
    public String getAccountName()
    {
+       if (getClient() == null)
+       return getAccountNamePlayer();
        return _accountName;
    }
-  
+   public String getAccountNamePlayer()
+   {
+   return _accountName;
+   }
    public Map<Integer, String> getAccountChars()
    {
        return _chars;
@@ -4113,6 +4118,8 @@
    public void setStoreType(StoreType type)
    {
        _storeType = type;
+       if (Config.OFFLINE_DISCONNECT_FINISHED && type == StoreType.NONE && (getClient() == null || getClient().isDetached()))
+           deleteMe();
    }
   
    /**
@@ -4122,7 +4129,16 @@
    {
        return _storeType;
    }
+   private long _offlineShopStart;
+   public long getOfflineStartTime()
+   {
+       return _offlineShopStart;
+   }
   
+   public void setOfflineStartTime(long time)
+   {
+       _offlineShopStart = time;
+   }
    /**
     * @return true if the {@link Player} can use dwarven recipes.
     */
diff --git a/java/net/sf/l2j/gameserver/network/GameClient.java b/java/net/sf/l2j/gameserver/network/GameClient.java
index 5218e60..823728e 100644
--- a/java/net/sf/l2j/gameserver/network/GameClient.java
+++ b/java/net/sf/l2j/gameserver/network/GameClient.java
@@ -21,9 +21,12 @@
 import net.sf.l2j.gameserver.LoginServerThread;
 import net.sf.l2j.gameserver.data.sql.ClanTable;
 import net.sf.l2j.gameserver.data.sql.PlayerInfoTable;
+import net.sf.l2j.gameserver.enums.MessageType;
+import net.sf.l2j.gameserver.enums.ZoneId;
 import net.sf.l2j.gameserver.model.CharSelectSlot;
 import net.sf.l2j.gameserver.model.World;
 import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.olympiad.OlympiadManager;
 import net.sf.l2j.gameserver.model.pledge.Clan;
 import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
 import net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket;
@@ -208,6 +211,29 @@
                if (getPlayer() != null && !isDetached())
                {
                    setDetached(true);
+                   if (offlineMode(getPlayer()))
+                   {
+                       if (getPlayer().getParty() != null)
+                           getPlayer().getParty().removePartyMember(getPlayer(), MessageType.EXPELLED);
+                       OlympiadManager.getInstance().unRegisterNoble(getPlayer());
+                      
+                       // If the Character has Pet, unsummon it
+                       if (getPlayer().hasPet())
+                       {
+                           getPlayer().getSummon().unSummon(getPlayer());
+                           // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline)
+                           if (getPlayer().getSummon() != null)
+                               getPlayer().getSummon().updateAndBroadcastStatus(0);
+                       }
+                      
+                       if (Config.OFFLINE_SET_SLEEP)
+                           getPlayer().startAbnormalEffect(0x000080);
+                      
+                       if (getPlayer().getOfflineStartTime() == 0)
+                           getPlayer().setOfflineStartTime(System.currentTimeMillis());
+                      
+                       return;
+                   }
                    fast = !getPlayer().isInCombat() && !getPlayer().isLocked();
                }
                cleanMe(fast);
@@ -218,6 +244,44 @@
        }
    }
   
+   /**
+    * @param player the player to be check.
+    * @return {@code true} if the player is allowed to remain as off-line shop.
+    */
+   public static boolean offlineMode(Player player)
+   {
+       if (player.isInOlympiadMode() || player.isFestivalParticipant() || player.isInJail() || player.getBoat() != null)
+           return false;
+      
+       boolean canSetShop = false;
+       switch (player.getStoreType())
+       {
+           case SELL:
+           case PACKAGE_SELL:
+           case BUY:
+           {
+               canSetShop = Config.OFFLINE_TRADE_ENABLE;
+               break;
+           }
+           case MANUFACTURE:
+           {
+               canSetShop = Config.OFFLINE_TRADE_ENABLE;
+               break;
+           }
+           default:
+           {
+               canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isCrafting();
+               break;
+           }
+       }
+      
+       if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE))
+           canSetShop = false;
+      
+       return canSetShop;
+   }
+
+
    @Override
    protected void onForcedDisconnection()
    {
@@ -580,6 +644,8 @@
   
    public void close(L2GameServerPacket gsp)
    {
+       if (getConnection() == null)
+       return;
        getConnection().close(gsp);
    }
   
 
Criar Tabela SQL
 
+character_offline_trade_items
+CREATE TABLE IF NOT EXISTS `character_offline_trade_items` (
+  `charId` int(10) NOT NULL DEFAULT 0,
+  `item` int(10) NOT NULL DEFAULT 0,
+  `count` int(20) NOT NULL DEFAULT 0,
+  `price` int(20) NOT NULL DEFAULT 0,
+  `enchant` int(20) NOT NULL DEFAULT 0
+);
 
+character_offline_trade
+CREATE TABLE IF NOT EXISTS `character_offline_trade` (
+  `charId` int(11) NOT NULL,
+  `time` bigint(20) unsigned NOT NULL DEFAULT 0,
+  `type` tinyint(4) NOT NULL DEFAULT 0,
+  `title` varchar(100) DEFAULT NULL,
+  PRIMARY KEY (`charId`)
+);
 
TOOLS
database_installer.bat
%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_memo.sql
+%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_offline_trade.sql
+%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_offline_trade_items.sql
%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_quests.sql
 
database_installer.sh
$MYG < ../sql/character_memo.sql &> /dev/null
+$MYG < ../sql/character_offline_trade.sql &> /dev/null
+$MYG < ../sql/character_offline_trade_items.sql &> /dev/null
$MYG < ../sql/character_quests.sql &> /dev/null
 
full_instal.sql
DROP TABLE IF EXISTS character_memo;
+DROP TABLE IF EXISTS character_offline_trade;
+DROP TABLE IF EXISTS character_offline_trade_items;
DROP TABLE IF EXISTS character_quests;
 
 
Index: DataPack
 
+# =================================================================
+#                       Offline trade/craft
+# =================================================================
+
+# Option to enable or disable offline trade feature.
+# Enable -> true, Disable -> false
+OfflineTradeEnable = True
+
+# Option to enable or disable offline craft feature.
+# Enable -> true, Disable -> false
+OfflineCraftEnable = True
+
+# If set to True, off-line shops will be possible only in peace zones.
+# Default: False
+OfflineModeInPeaceZone = True
+
+# If set to True, players in off-line shop mode will not take any damage, thus they cannot be killed.
+# Default: False
+OfflineModeNoDamage = False
+
+# Restore offline traders/crafters after restart/shutdown.
+# Default: False
+RestoreOffliners = True
+
+# Do not restore offline characters, after OfflineMaxDays days spent from first restore.
+# Require server restart to disconnect expired shops.
+# 0 = disabled (always restore).
+# Default: 7
+OfflineMaxDays = 7
+
+# Disconnect shop after finished selling, buying.
+# Default: True
+OfflineDisconnectFinished = True
+
+#Offline Effect Sleep
+OfflineSetSleepEffect = True

Под более раннюю версию, но в должно сработать и у тебя, если импорты под 409 поменять
спасибо вроде перелопатил все , вроде как все работает
 
Назад
Сверху Снизу