[phpBB Debug] PHP Warning: in file [ROOT]/phpbb/session.php on line 583: sizeof(): Parameter must be an array or an object that implements Countable
[phpBB Debug] PHP Warning: in file [ROOT]/phpbb/session.php on line 639: sizeof(): Parameter must be an array or an object that implements Countable
L2J Server • Restore offliners on Gracia Final CT 2.3?
Page 1 of 1

Restore offliners on Gracia Final CT 2.3?

Posted: Wed Jul 25, 2018 8:24 pm
by regenx
Hi everyone, can anyone help please?
Ive added this script:

Code: Select all

Index: java/com/l2jserver/Config.java===================================================================
--- java/com/l2jserver/Config.java	(revision 4196)
+++ java/com/l2jserver/Config.java	(working copy)@@ -657,6 +657,9 @@ 	
public static boolean L2JMOD_ENABLE_WAREHOUSESORTING_PRIVATE; 	
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;

@@ -2224,6 +2227,9 @@ 					
OFFLINE_SET_NAME_COLOR = Boolean.parseBoolean(L2JModSettings.getProperty("OfflineSetNameColor", "false")); 					
OFFLINE_NAME_COLOR = Integer.decode("0x" + L2JModSettings.getProperty("OfflineNameColor", "808080")); 					
OFFLINE_FAME = Boolean.parseBoolean(L2JModSettings.getProperty("OfflineFame", "true"));
+					RESTORE_OFFLINERS = Boolean.parseBoolean(L2JModSettings.getProperty("RestoreOffliners", "false")); 
+					OFFLINE_MAX_DAYS = Integer.parseInt(L2JModSettings.getProperty("OfflineMaxDays", "10"));
+					OFFLINE_DISCONNECT_FINISHED = Boolean.parseBoolean(L2JModSettings.getProperty("OfflineDisconnectFinished", "true"));  					
L2JMOD_ENABLE_MANA_POTIONS_SUPPORT = Boolean.parseBoolean(L2JModSettings.getProperty("EnableManaPotionSupport", "false")); 










Index: java/com/l2jserver/gameserver/GameServer.java===================================================================
--- java/com/l2jserver/gameserver/GameServer.java	(revision 4196)
+++ java/com/l2jserver/gameserver/GameServer.java	(working copy)

@@ -61,6 +61,7 @@ 
import net.sf.l2j.gameserver.datatables.NpcBufferTable; 
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.PetSkillsTable; 
import net.sf.l2j.gameserver.datatables.ResidentialSkillTable;

@@ -413,6 +414,10 @@  		
TvTManager.getInstance(); 		
KnownListUpdateTaskManager.getInstance();
+		
+		if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)
+			OfflineTradersTable.restoreOfflineTraders(); 
+		 		if (Config.DEADLOCK_DETECTOR) 		{ 			_deadDetectThread = new DeadLockDetector();










Index: java/com/l2jserver/gameserver/Shutdown.java===================================================================
--- java/com/l2jserver/gameserver/Shutdown.java	(revision 4196)
+++ java/com/l2jserver/gameserver/Shutdown.java	(working copy)
@@ -15,11 +15,13 @@ 
package com.l2jserver.gameserver;  
import java.util.Collection;
+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.datatables.ClanTable;
+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;

@@ -204,6 +206,16 @@ 		
{ 			
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);
+			}
+				
+			try
+			{ 				
disconnectAllCharacters(); 				
_log.info("All players disconnected."); 			
}









Index: java/com/l2jserver/gameserver/datatables/OfflineTradersTable.java
===================================================================
--- java/com/l2jserver/gameserver/datatables/OfflineTradersTable.java	(revision 0)
+++ java/com/l2jserver/gameserver/datatables/OfflineTradersTable.java	(revision 0)
@@ -0,0 +1,270 @@
+/*
+ * 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.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.setLong(3, i.getCount());
+									stm_items.setLong(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.setLong(3, i.getCount());
+									stm_items.setLong(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)
+			{
+				
+			}
+		}
+	}
+	
+	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.roll(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);
+					client.setAccountName(player.getAccountNamePlayer());
+					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())
+							{
+								player.getBuyList().addItemByItemId(items.getInt(2), items.getLong(3), items.getLong(4));
+							}
+							player.getBuyList().setTitle(rs.getString("title"));
+							break;
+						case L2PcInstance.STORE_PRIVATE_SELL:
+						case L2PcInstance.STORE_PRIVATE_PACKAGE_SELL:
+							while (items.next())
+							{
+								player.getSellList().addItem(items.getInt(2), items.getLong(3), items.getLong(4));
+							}
+							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.getLong(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);
+					player.restoreEffects();
+					player.broadcastUserInfo();
+					nTraders++;
+				}
+				catch (Exception e)
+				{
+					_log.log(Level.WARNING, "OfflineTradersTable[loadOffliners()]: Error loading trader: ",e);
+					if (player != null)
+						player.logout();
+				}
+			}
+			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)
+			{
+				
+			}
+		}
+	}
+}








Index: java/com/l2jserver/gameserver/idfactory/IdFactory.java===================================================================
--- java/com/l2jserver/gameserver/idfactory/IdFactory.java	(revision 4200)
+++ java/com/l2jserver/gameserver/idfactory/IdFactory.java	(working copy)

@@ -66,6 +66,8 @@ 	        
"UPDATE olympiad_fights SET charTwoId = ? WHERE charTwoId = ?", 	        
"UPDATE heroes_diary SET charId = ? WHERE charId = ?", 	        
"UPDATE olympiad_nobles SET charId = ? WHERE charId = ?",
+	        "UPDATE character_offline_trade SET charId = ? WHERE charId = ?",
+	        "UPDATE character_offline_trade_items SET charId = ? WHERE charId = ?", 	        
"UPDATE clanhall SET ownerId = ? WHERE ownerId = ?" };  	
protected static final String[] ID_CHECKS = {

@@ -228,6 +230,8 @@ 			
cleanCount += stmt.executeUpdate("DELETE FROM olympiad_fights WHERE olympiad_fights.charOneId NOT IN (SELECT charId FROM characters);"); 			
cleanCount += stmt.executeUpdate("DELETE FROM olympiad_fights WHERE olympiad_fights.charTwoId NOT IN (SELECT charId FROM characters);"); 			
cleanCount += stmt.executeUpdate("DELETE FROM heroes_diary WHERE heroes_diary.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_offline_trade WHERE character_offline_trade.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_offline_trade_items WHERE character_offline_trade_items.charId NOT IN (SELECT charId FROM characters);");  			
// If the clan does not exist... 			
cleanCount += stmt.executeUpdate("DELETE FROM clan_privs WHERE clan_privs.clan_id NOT IN (SELECT clan_id FROM clan_data);");










Index: java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java===================================================================
--- java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java	(revision 4201)
+++ java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java	(working copy)

@@ -516,6 +516,8 @@ 	
private boolean _inCrystallize; 	
private boolean _inCraftMode; 
+	private long _offlineShopStart = 0;
private L2Transformation _transformation; 	
private int _transformationId = 0; 

@@ -6382,6 +6384,9 @@ 	
public void setPrivateStoreType(int type) 	{ 		
_privatestore = type;
+		
+		if (Config.OFFLINE_DISCONNECT_FINISHED && _privatestore == STORE_PRIVATE_NONE && (getClient() == null || getClient().isDetached()))
+			logout();  	
}  	
/**
@@ -14840,4 +14845,14 @@  		
return result; 	
}
+
+	public long getOfflineStartTime()
+	{
+		return _offlineShopStart;
+	}
+	
+	public void setOfflineStartTime(long time)
+	{
+		_offlineShopStart = time;
+	} 
}







Index: java/com/l2jserver/gameserver/network/L2GameClient.java===================================================================
--- java/com/l2jserver/gameserver/network/L2GameClient.java	(revision 4196)
+++ java/com/l2jserver/gameserver/network/L2GameClient.java	(working copy)
@@ -633,6 +633,8 @@ 								
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});











Index: java/com/l2jserver/gameserver/network/clientpackets/Logout.java===================================================================
--- java/com/l2jserver/gameserver/network/clientpackets/Logout.java	(revision 4196)
+++ java/com/l2jserver/gameserver/network/clientpackets/Logout.java	(working copy)
@@ -104,6 +104,8 @@ 		
{ 			
player.getInventory().updateDatabase(); 			
player.closeNetConnection(true);
+			if (player.getOfflineStartTime() == 0)
+				player.setOfflineStartTime(System.currentTimeMillis()); 			
return; 		
} 









Index: java/config/l2jmods.properties===================================================================
--- java/config/l2jmods.properties	(revision 4196)
+++ java/config/l2jmods.properties	(working copy)
@@ -253,6 +253,19 @@ 
# Enable -> true, Disable -> false 
OfflineFame = True 
+#Restore offline traders/crafters after restart/shutdown. Default: false.
+RestoreOffliners = False
+
+#Do not restore offline characters, after OfflineMaxDays days spent from first restore.
+#Require server restart to disconnect expired shops.
+#0 = disabled (always restore).
+#Default: 10
+OfflineMaxDays = 10 
+
+#Disconnect shop after finished selling, buying.
+#Default: True
+OfflineDisconnectFinished = True
+ # --------------------------------------------------------------------------- 
# Mana Drugs/Potions 
# ---------------------------------------------------------------------------


Errors after compiled..

Code: Select all

TvTEventEngine[TvTManager.TvTManager()]: Started.
Loading offline traders...
OfflineTradersTable[loadOffliners()]: Error loading trader: 
java.lang.NullPointerException
	at net.sf.l2j.gameserver.network.L2GameClient.sendPacket(L2GameClient.java:206)
	at net.sf.l2j.gameserver.model.actor.instance.L2PcInstance.sendPacket(L2PcInstance.java:4583)
	at net.sf.l2j.gameserver.model.actor.L2Npc.sendInfo(L2Npc.java:2733)
	at net.sf.l2j.gameserver.model.actor.knownlist.PcKnownList.addKnownObject(PcKnownList.java:81)
	at net.sf.l2j.gameserver.model.L2World.addVisibleObject(L2World.java:363)
	at net.sf.l2j.gameserver.model.L2Object.spawnMe(L2Object.java:293)
	at net.sf.l2j.gameserver.datatables.OfflineTradersTable.restoreOfflineTraders(OfflineTradersTable.java:191)
	at net.sf.l2j.gameserver.GameServer.<init>(GameServer.java:409)
	at net.sf.l2j.gameserver.GameServer.main(GameServer.java:495)

OfflineTradersTable[loadOffliners()]: Error while loading offline traders: 
java.lang.NullPointerException
	at net.sf.l2j.gameserver.model.actor.instance.L2PcInstance.closeNetConnection(L2PcInstance.java:4060)
	at net.sf.l2j.gameserver.model.actor.instance.L2PcInstance.logout(L2PcInstance.java:1312)
	at net.sf.l2j.gameserver.datatables.OfflineTradersTable.restoreOfflineTraders(OfflineTradersTable.java:241)
	at net.sf.l2j.gameserver.GameServer.<init>(GameServer.java:409)
	at net.sf.l2j.gameserver.GameServer.main(GameServer.java:495)

Please Help !! :crazy:

Re: Restore offliners on Gracia Final CT 2.3?

Posted: Fri Jul 27, 2018 9:14 pm
by regenx
Anyone please? Some advices?
On Epilogue CT 2.4 is working, I've changed the imports but something is missing for Gracia Final CT 2.3 and restore_offliners are not working...
HELP !!! Please! :crazy:

Re: Restore offliners on Gracia Final CT 2.3?

Posted: Fri Jul 27, 2018 10:28 pm
by JMD
regenx wrote:
Fri Jul 27, 2018 9:14 pm
Anyone please? Some advices?
On Epilogue CT 2.4 is working, I've changed the imports but something is missing for Gracia Final CT 2.3 and restore_offliners are not working...
HELP !!! Please! :crazy:
Maybe this can help you somewhat.

http://www.mediafire.com/file/gy88g7aev ... inal%29.7z

Re: Restore offliners on Gracia Final CT 2.3?

Posted: Sun Jul 29, 2018 9:55 pm
by regenx
Thanks a lot. Yes, it is good for Birthday Manager and some other useful stuff.

But there are no Offline Shops too. Missing..

Pfff... :( I can't find a solution for this..
Question: It is possible to save manually all private stores, somehow? Because when server is restarting there is a clean up function or smth like that and will not be saved.

Re: Restore offliners on Gracia Final CT 2.3?

Posted: Tue Jul 31, 2018 7:55 am
by regenx
I tried everything and nothing works :crazy:

My offline shops are saved in 'characters' table with online=1 and not online=2

Is there another way to save my offline shops?
Can I save them manually? :eh:

Please help!

Re: Restore offliners on Gracia Final CT 2.3?

Posted: Mon Feb 04, 2019 2:49 pm
by regenx
On L2J Server Epilogue CT 2.4 .. Offline Shops have online=2 in characters table from DB .. but on same L2J Gracia Final CT 2.3 online=1
It is normal? Any FIX? :?
Of course it is not normal.. I tested with latest L2J GF from bitbucket.


Anyone can help?