Chronicle 4 branch.

This commit is contained in:
MobiusDev
2017-07-19 21:24:06 +00:00
parent 9a69bec286
commit 3a0bf3539a
13496 changed files with 641683 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,327 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* This class manages the database connections.
*/
public class L2DatabaseFactory
{
private static Logger _log = Logger.getLogger(L2DatabaseFactory.class.getName());
public static enum ProviderType
{
MySql,
MsSql
}
// =========================================================
// Data Field
private static L2DatabaseFactory _instance;
private static volatile ScheduledExecutorService _executor;
private ProviderType _Provider_Type;
private ComboPooledDataSource _source;
// =========================================================
// Constructor
public L2DatabaseFactory() throws SQLException
{
try
{
if (Config.DATABASE_MAX_CONNECTIONS < 2)
{
Config.DATABASE_MAX_CONNECTIONS = 2;
_log.warning("at least " + Config.DATABASE_MAX_CONNECTIONS + " db connections are required.");
}
_source = new ComboPooledDataSource();
_source.setAutoCommitOnClose(true);
_source.setInitialPoolSize(3); // 3 is the default for c3p0 anyway
// if > MaxPoolSize, it will be ignored - no worry
// (as said in c3p0 docs, it's only a suggestion
// how many connections to acquire to start with)
_source.setMinPoolSize(1);
_source.setMaxPoolSize(Config.DATABASE_MAX_CONNECTIONS);
_source.setAcquireRetryAttempts(0); // try to obtain connections indefinitely (0 = never quit)
_source.setAcquireRetryDelay(500); // 500 miliseconds wait before try to acquire connection again
_source.setCheckoutTimeout(0); // 0 = wait indefinitely for new connection
// if pool is exhausted
_source.setAcquireIncrement(5); // if pool is exhausted, get 5 more connections at a time
// cause there is a "long" delay on acquire connection
// so taking more than one connection at once will make connection pooling
// more effective.
// this "connection_test_table" is automatically created if not already there
_source.setAutomaticTestTable("connection_test_table"); // very very fast test, don't worry
_source.setTestConnectionOnCheckin(true); // this will *not* make l2j slower in any way
// testing OnCheckin used with IdleConnectionTestPeriod is faster than testing on checkout
_source.setIdleConnectionTestPeriod(60); // test idle connection every 60 sec
_source.setMaxIdleTime(0); // 0 = idle connections never expire
// *THANKS* to connection testing configured above
// but I prefer to disconnect all connections not used
// for more than 1 hour
// enables statement caching, there is a "semi-bug" in c3p0 0.9.0 but in 0.9.0.2 and later it's fixed
_source.setMaxStatementsPerConnection(100);
_source.setBreakAfterAcquireFailure(false); // never fail if any way possible
// setting this to true will make
// c3p0 "crash" and refuse to work
// till restart thus making acquire
// errors "FATAL" ... we don't want that
// it should be possible to recover
_source.setDriverClass(Config.DATABASE_DRIVER);
_source.setJdbcUrl(Config.DATABASE_URL);
_source.setUser(Config.DATABASE_LOGIN);
_source.setPassword(Config.DATABASE_PASSWORD);
/* Test the connection */
_source.getConnection().close();
if (Config.DEBUG)
{
_log.fine("Database Connection Working");
}
if (Config.DATABASE_DRIVER.toLowerCase().contains("microsoft"))
{
_Provider_Type = ProviderType.MsSql;
}
else
{
_Provider_Type = ProviderType.MySql;
}
}
catch (final SQLException x)
{
if (Config.DEBUG)
{
_log.fine("Database Connection FAILED");
}
// rethrow the exception
throw x;
}
catch (final Exception e)
{
if (Config.DEBUG)
{
_log.fine("Database Connection FAILED");
}
throw new SQLException("could not init DB connection:" + e);
}
}
// =========================================================
// Method - Public
public final String prepQuerySelect(String[] fields, String tableName, String whereClause, boolean returnOnlyTopRecord)
{
String msSqlTop1 = "";
String mySqlTop1 = "";
if (returnOnlyTopRecord)
{
if (getProviderType() == ProviderType.MsSql)
{
msSqlTop1 = " Top 1 ";
}
if (getProviderType() == ProviderType.MySql)
{
mySqlTop1 = " Limit 1 ";
}
}
final String query = "SELECT " + msSqlTop1 + safetyString(fields) + " FROM " + tableName + " WHERE " + whereClause + mySqlTop1;
return query;
}
public void shutdown()
{
try
{
_source.close();
}
catch (final Exception e)
{
_log.log(Level.INFO, "", e);
}
try
{
_source = null;
}
catch (final Exception e)
{
_log.log(Level.INFO, "", e);
}
}
public final String safetyString(String... whatToCheck)
{
// NOTE: Use brace as a safety percaution just incase name is a reserved word
String braceLeft = "`";
String braceRight = "`";
if (getProviderType() == ProviderType.MsSql)
{
braceLeft = "[";
braceRight = "]";
}
String result = "";
for (final String word : whatToCheck)
{
if (!result.isEmpty())
{
result += ", ";
}
result += braceLeft + word + braceRight;
}
return result;
}
// =========================================================
// Property - Public
public static L2DatabaseFactory getInstance() throws SQLException
{
synchronized (L2DatabaseFactory.class)
{
if (_instance == null)
{
_instance = new L2DatabaseFactory();
}
}
return _instance;
}
/**
* Gets the connection.
* @return the connection
*/
public Connection getConnection()
{
Connection con = null;
while (con == null)
{
try
{
con = _source.getConnection();
if (Server.SERVER_MODE == Server.MODE_GAMESERVER)
{
ThreadPoolManager.getInstance().scheduleGeneral(new ConnectionCloser(con, new RuntimeException()), Config.CONNECTION_CLOSE_TIME);
}
else
{
getExecutor().schedule(new ConnectionCloser(con, new RuntimeException()), Config.CONNECTION_CLOSE_TIME, TimeUnit.MILLISECONDS);
}
}
catch (final SQLException e)
{
_log.warning("L2DatabaseFactory: getConnection() failed, trying again " + e);
}
}
return con;
}
/**
* The Class ConnectionCloser.
*/
private static class ConnectionCloser implements Runnable
{
private static final Logger _log = Logger.getLogger(ConnectionCloser.class.getName());
/** The connection. */
private final Connection c;
/** The exception. */
private final RuntimeException exp;
/**
* Instantiates a new connection closer.
* @param con the con
* @param e the e
*/
public ConnectionCloser(Connection con, RuntimeException e)
{
c = con;
exp = e;
}
@Override
public void run()
{
try
{
if (!c.isClosed())
{
_log.log(Level.WARNING, "Unclosed connection! Trace: " + exp.getStackTrace()[1], exp);
}
}
catch (final SQLException e)
{
_log.log(Level.WARNING, "", e);
}
}
}
/**
* Gets the executor.
* @return the executor
*/
private static ScheduledExecutorService getExecutor()
{
if (_executor == null)
{
synchronized (L2DatabaseFactory.class)
{
if (_executor == null)
{
_executor = Executors.newSingleThreadScheduledExecutor();
}
}
}
return _executor;
}
public int getBusyConnectionCount() throws SQLException
{
return _source.getNumBusyConnectionsDefaultUser();
}
public int getIdleConnectionCount() throws SQLException
{
return _source.getNumIdleConnectionsDefaultUser();
}
public final ProviderType getProviderType()
{
return _Provider_Type;
}
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius;
/**
* This class used to be the starter class, since LS/GS split, it only retains server mode
*/
public class Server
{
// constants for the server mode
public static final int MODE_NONE = 0;
public static final int MODE_GAMESERVER = 1;
public static final int MODE_LOGINSERVER = 2;
public static int SERVER_MODE = MODE_NONE;
}

View File

@@ -0,0 +1,245 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.clientpackets.Say2;
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.script.DateRange;
import javolution.text.TextBuilder;
import javolution.util.FastList;
/**
* This class ...
* @version $Revision: 1.5.2.1.2.7 $ $Date: 2005/03/29 23:15:14 $
*/
public class Announcements
{
private static Logger _log = Logger.getLogger(Announcements.class.getName());
private static Announcements _instance;
private final List<String> _announcements = new FastList<>();
private final List<List<Object>> eventAnnouncements = new FastList<>();
public Announcements()
{
loadAnnouncements();
}
public static Announcements getInstance()
{
if (_instance == null)
{
_instance = new Announcements();
}
return _instance;
}
public void loadAnnouncements()
{
_announcements.clear();
final File file = new File(Config.DATAPACK_ROOT, "data/announcements.txt");
if (file.exists())
{
readFromDisk(file);
}
else
{
_log.config("data/announcements.txt doesn't exist");
}
}
public void showAnnouncements(L2PcInstance activeChar)
{
for (int i = 0; i < _announcements.size(); i++)
{
final CreatureSay cs = new CreatureSay(0, Say2.ANNOUNCEMENT, activeChar.getName(), _announcements.get(i).toString());
activeChar.sendPacket(cs);
}
for (int i = 0; i < eventAnnouncements.size(); i++)
{
final List<Object> entry = eventAnnouncements.get(i);
final DateRange validDateRange = (DateRange) entry.get(0);
final String[] msg = (String[]) entry.get(1);
final Date currentDate = new Date();
if (!validDateRange.isValid() || validDateRange.isWithinRange(currentDate))
{
final SystemMessage sm = new SystemMessage(SystemMessage.S1_S2);
for (final String element : msg)
{
sm.addString(element);
}
activeChar.sendPacket(sm);
}
}
}
public void addEventAnnouncement(DateRange validDateRange, String[] msg)
{
final List<Object> entry = new FastList<>();
entry.add(validDateRange);
entry.add(msg);
eventAnnouncements.add(entry);
}
public void listAnnouncements(L2PcInstance activeChar)
{
final NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
final TextBuilder replyMSG = new TextBuilder("<html><body>");
replyMSG.append("<table width=260><tr>");
replyMSG.append("<td width=40><button value=\"Main\" action=\"bypass -h admin_admin\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
replyMSG.append("<td width=180><center>Announcement Menu</center></td>");
replyMSG.append("<td width=40><button value=\"Back\" action=\"bypass -h admin_admin\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
replyMSG.append("</tr></table>");
replyMSG.append("<br><br>");
replyMSG.append("<center>Add or announce a new announcement:</center>");
replyMSG.append("<center><multiedit var=\"new_announcement\" width=240 height=30></center><br>");
replyMSG.append("<center><table><tr><td>");
replyMSG.append("<button value=\"Add\" action=\"bypass -h admin_add_announcement $new_announcement\" width=60 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td><td>");
replyMSG.append("<button value=\"Announce\" action=\"bypass -h admin_announce_menu $new_announcement\" width=60 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td><td>");
replyMSG.append("<button value=\"Reload\" action=\"bypass -h admin_announce_announcements\" width=60 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\">");
replyMSG.append("</td></tr></table></center>");
replyMSG.append("<br>");
for (int i = 0; i < _announcements.size(); i++)
{
replyMSG.append("<table width=260><tr><td width=220>" + _announcements.get(i).toString() + "</td><td width=40>");
replyMSG.append("<button value=\"Delete\" action=\"bypass -h admin_del_announcement " + i + "\" width=60 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr></table>");
}
replyMSG.append("</body></html>");
adminReply.setHtml(replyMSG.toString());
activeChar.sendPacket(adminReply);
}
public void addAnnouncement(String text)
{
_announcements.add(text);
saveToDisk();
}
public void delAnnouncement(int line)
{
_announcements.remove(line);
saveToDisk();
}
private void readFromDisk(File file)
{
try (FileReader fr = new FileReader(file);
LineNumberReader lnr = new LineNumberReader(fr))
{
String line = null;
while ((line = lnr.readLine()) != null)
{
final StringTokenizer st = new StringTokenizer(line, "\n\r");
if (st.hasMoreTokens())
{
final String announcement = st.nextToken();
_announcements.add(announcement);
}
}
_log.config("Announcements: Loaded " + _announcements.size() + " Announcements.");
}
catch (final IOException e1)
{
_log.log(Level.SEVERE, "Error reading announcements", e1);
}
}
private void saveToDisk()
{
final File file = new File("data/announcements.txt");
try (FileWriter save = new FileWriter(file))
{
for (int i = 0; i < _announcements.size(); i++)
{
save.write(_announcements.get(i).toString());
save.write("\r\n");
}
save.flush();
}
catch (final IOException e)
{
_log.warning("saving the announcements file has failed: " + e);
}
}
public void announceToAll(String text)
{
final CreatureSay cs = new CreatureSay(0, Say2.ANNOUNCEMENT, "", text);
for (final L2PcInstance player : L2World.getInstance().getAllPlayers())
{
if (player == null)
{
continue;
}
player.sendPacket(cs);
}
}
public void announceToAll(SystemMessage sm)
{
for (final L2PcInstance player : L2World.getInstance().getAllPlayers())
{
if (player == null)
{
continue;
}
player.sendPacket(sm);
}
}
// Method fo handling announcements from admin
public void handleAnnounce(String command, int lengthToTrim)
{
try
{
// Announce string to everyone on server
final String text = command.substring(lengthToTrim);
Announcements.getInstance().announceToAll(text);
}
catch (final StringIndexOutOfBoundsException e)
{
// Nobody cares!
// empty message.. ignore
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.instancemanager.CastleManager;
import com.l2jmobius.gameserver.model.ItemContainer;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.entity.Castle;
/**
* Thorgrim - 2005 Class managing periodical events with castle manor
*/
public class CastleManorUpdater implements Runnable
{
protected static Logger _log = Logger.getLogger(CastleManorUpdater.class.getName());
private final L2Clan _clan;
private int _runCount = 0;
public CastleManorUpdater(L2Clan clan, int runCount)
{
_clan = clan;
_runCount = runCount;
}
@Override
public void run()
{
try
{
// Move current castle treasury to clan warehouse every 2 hour
final ItemContainer warehouse = _clan.getWarehouse();
if ((warehouse != null) && (_clan.getHasCastle() > 0))
{
final Castle castle = CastleManager.getInstance().getCastleById(_clan.getHasCastle());
if (!Config.ALT_MANOR_SAVE_ALL_ACTIONS)
{
if ((_runCount % Config.ALT_MANOR_SAVE_PERIOD_RATE) == 0)
{
castle.saveSeedData();
castle.saveCropData();
_log.info("Manor System: all data for " + castle.getName() + " saved");
}
}
_runCount++;
final CastleManorUpdater cmu = new CastleManorUpdater(_clan, _runCount);
ThreadPoolManager.getInstance().scheduleGeneral(cmu, 3600000);
}
}
catch (final Throwable e)
{
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,119 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.util.Date;
import java.util.List;
import com.l2jmobius.gameserver.script.DateRange;
import javolution.util.FastList;
/**
* This class manage drop of Special Events created by GM for a defined period. During a Special Event all L2Attackable can drop extra Items. Those extra Items are defined in the table <B>allNpcDateDrops</B>. Each Special Event has a start and end date to stop to drop extra Items automaticaly.<BR>
* <BR>
*/
public class EventDroplist
{
// private static Logger _log = Logger.getLogger(EventDroplist.class.getName());
private static EventDroplist _instance;
/** The table containing all DataDrop object */
private final List<DateDrop> allNpcDateDrops;
public static EventDroplist getInstance()
{
if (_instance == null)
{
_instance = new EventDroplist();
}
return _instance;
}
public class DateDrop
{
/** Start and end date of the Event */
DateRange dateRange;
/** The table containing Item identifier that can be dropped as extra Items during the Event */
public int[] items;
/** The min number of Item dropped in one time during this Event */
public int min;
/** The max number of Item dropped in one time during this Event */
public int max;
/** The rate of drop for this Event */
public int chance;
}
/**
* Constructor of EventDroplist.<BR>
* <BR>
*/
private EventDroplist()
{
allNpcDateDrops = new FastList<>();
}
/**
* Create and Init a new DateDrop then add it to the allNpcDateDrops of EventDroplist .<BR>
* <BR>
* @param items The table containing all item identifier of this DateDrop
* @param count The table containing min and max value of this DateDrop
* @param chance The chance to obtain this drop
* @param range The DateRange object to add to this DateDrop
*/
public void addGlobalDrop(int[] items, int[] count, int chance, DateRange range)
{
final DateDrop date = new DateDrop();
date.dateRange = range;
date.items = items;
date.min = count[0];
date.max = count[1];
date.chance = chance;
allNpcDateDrops.add(date);
}
/**
* Return all DateDrop of EventDroplist allNpcDateDrops within the date range.<BR>
* <BR>
* @return
*/
public List<DateDrop> getAllDrops()
{
final List<DateDrop> list = new FastList<>();
for (final DateDrop drop : allNpcDateDrops)
{
final Date currentDate = new Date();
// System.out.println("From: "+drop.from+" To: "+drop.to+" Now: "+ currentDate);
if (drop.dateRange.isWithinRange(currentDate))
{
list.add(drop);
}
}
return list;
}
}

View File

@@ -0,0 +1,90 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
/**
* @author KenM
*/
public class GameCrypt
{
private final byte[] _inKey = new byte[8];
private final byte[] _outKey = new byte[8];
private boolean _isEnabled;
public void setKey(byte[] key)
{
System.arraycopy(key, 0, _inKey, 0, 8);
System.arraycopy(key, 0, _outKey, 0, 8);
}
public void decrypt(byte[] raw, final int offset, final int size)
{
if (!_isEnabled)
{
return;
}
int temp = 0;
for (int i = 0; i < size; i++)
{
final int temp2 = raw[offset + i] & 0xFF;
raw[offset + i] = (byte) (temp2 ^ _inKey[i & 7] ^ temp);
temp = temp2;
}
int old = _inKey[0] & 0xff;
old |= (_inKey[1] << 8) & 0xff00;
old |= (_inKey[2] << 0x10) & 0xff0000;
old |= (_inKey[3] << 0x18) & 0xff000000;
old += size;
_inKey[0] = (byte) (old & 0xff);
_inKey[1] = (byte) ((old >> 0x08) & 0xff);
_inKey[2] = (byte) ((old >> 0x10) & 0xff);
_inKey[3] = (byte) ((old >> 0x18) & 0xff);
}
public void encrypt(byte[] raw, final int offset, final int size)
{
if (!_isEnabled)
{
_isEnabled = true;
return;
}
int temp = 0;
for (int i = 0; i < size; i++)
{
final int temp2 = raw[offset + i] & 0xFF;
temp = temp2 ^ _outKey[i & 7] ^ temp;
raw[offset + i] = (byte) temp;
}
int old = _outKey[0] & 0xff;
old |= (_outKey[1] << 8) & 0xff00;
old |= (_outKey[2] << 0x10) & 0xff0000;
old |= (_outKey[3] << 0x18) & 0xff000000;
old += size;
_outKey[0] = (byte) (old & 0xff);
_outKey[1] = (byte) ((old >> 0x08) & 0xff);
_outKey[2] = (byte) ((old >> 0x10) & 0xff);
_outKey[3] = (byte) ((old >> 0x18) & 0xff);
}
}

View File

@@ -0,0 +1,786 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import org.mmocore.network.SelectorConfig;
import org.mmocore.network.SelectorThread;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.Server;
import com.l2jmobius.gameserver.cache.CrestCache;
import com.l2jmobius.gameserver.cache.HtmCache;
import com.l2jmobius.gameserver.communitybbs.Manager.ForumsBBSManager;
import com.l2jmobius.gameserver.datatables.ArmorSetsTable;
import com.l2jmobius.gameserver.datatables.CharNameTable;
import com.l2jmobius.gameserver.datatables.CharTemplateTable;
import com.l2jmobius.gameserver.datatables.ClanTable;
import com.l2jmobius.gameserver.datatables.DoorTable;
import com.l2jmobius.gameserver.datatables.ExtractableItemsData;
import com.l2jmobius.gameserver.datatables.FishTable;
import com.l2jmobius.gameserver.datatables.GmListTable;
import com.l2jmobius.gameserver.datatables.HelperBuffTable;
import com.l2jmobius.gameserver.datatables.HennaTable;
import com.l2jmobius.gameserver.datatables.HennaTreeTable;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.datatables.LevelUpData;
import com.l2jmobius.gameserver.datatables.MapRegionTable;
import com.l2jmobius.gameserver.datatables.NobleSkillTable;
import com.l2jmobius.gameserver.datatables.NpcBufferTable;
import com.l2jmobius.gameserver.datatables.NpcTable;
import com.l2jmobius.gameserver.datatables.NpcWalkerRoutesTable;
import com.l2jmobius.gameserver.datatables.OfflineTradersTable;
import com.l2jmobius.gameserver.datatables.SkillSpellbookTable;
import com.l2jmobius.gameserver.datatables.SkillTable;
import com.l2jmobius.gameserver.datatables.SkillTreeTable;
import com.l2jmobius.gameserver.datatables.SpawnTable;
import com.l2jmobius.gameserver.datatables.StaticObjects;
import com.l2jmobius.gameserver.datatables.SummonItemsData;
import com.l2jmobius.gameserver.datatables.TeleportLocationTable;
import com.l2jmobius.gameserver.datatables.ZoneTable;
import com.l2jmobius.gameserver.geoeditorcon.GeoEditorListener;
import com.l2jmobius.gameserver.handler.AdminCommandHandler;
import com.l2jmobius.gameserver.handler.ItemHandler;
import com.l2jmobius.gameserver.handler.SkillHandler;
import com.l2jmobius.gameserver.handler.UserCommandHandler;
import com.l2jmobius.gameserver.handler.VoicedCommandHandler;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminAdmin;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminAnnouncements;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminBBS;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminBan;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminBanChat;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminCache;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminChangeAccessLevel;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminCreateItem;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminDelete;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminDisconnect;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminDoorControl;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminEditChar;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminEditNpc;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminEffects;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminEnchant;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminEventEngine;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminExpSp;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminFightCalculator;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGeoEditor;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGeodata;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGm;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminGmChat;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminHeal;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminHelpPage;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminInvul;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminKick;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminKill;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminLevel;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminLogin;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminMammon;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminManor;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminMenu;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminMobGroup;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminMonsterRace;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminPForge;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminPathNode;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminPetition;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminPledge;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminPolymorph;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminQuest;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminRepairChar;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminRes;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminRideWyvern;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminShop;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminShutdown;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminSiege;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminSkill;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminSpawn;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminTarget;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminTeleport;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminTest;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminUnblockIp;
import com.l2jmobius.gameserver.handler.admincommandhandlers.AdminZone;
import com.l2jmobius.gameserver.handler.itemhandlers.BeastSoulShot;
import com.l2jmobius.gameserver.handler.itemhandlers.BeastSpice;
import com.l2jmobius.gameserver.handler.itemhandlers.BeastSpiritShot;
import com.l2jmobius.gameserver.handler.itemhandlers.BlessedSpiritShot;
import com.l2jmobius.gameserver.handler.itemhandlers.Book;
import com.l2jmobius.gameserver.handler.itemhandlers.CharChangePotions;
import com.l2jmobius.gameserver.handler.itemhandlers.ChestKey;
import com.l2jmobius.gameserver.handler.itemhandlers.CrystalCarol;
import com.l2jmobius.gameserver.handler.itemhandlers.EnchantScrolls;
import com.l2jmobius.gameserver.handler.itemhandlers.EnergyStone;
import com.l2jmobius.gameserver.handler.itemhandlers.ExtractableItems;
import com.l2jmobius.gameserver.handler.itemhandlers.Firework;
import com.l2jmobius.gameserver.handler.itemhandlers.FishShots;
import com.l2jmobius.gameserver.handler.itemhandlers.Harvester;
import com.l2jmobius.gameserver.handler.itemhandlers.MercTicket;
import com.l2jmobius.gameserver.handler.itemhandlers.PetFood;
import com.l2jmobius.gameserver.handler.itemhandlers.Potions;
import com.l2jmobius.gameserver.handler.itemhandlers.Recipes;
import com.l2jmobius.gameserver.handler.itemhandlers.Remedy;
import com.l2jmobius.gameserver.handler.itemhandlers.RollingDice;
import com.l2jmobius.gameserver.handler.itemhandlers.ScrollOfEscape;
import com.l2jmobius.gameserver.handler.itemhandlers.ScrollOfResurrection;
import com.l2jmobius.gameserver.handler.itemhandlers.Scrolls;
import com.l2jmobius.gameserver.handler.itemhandlers.Seed;
import com.l2jmobius.gameserver.handler.itemhandlers.SevenSignsRecord;
import com.l2jmobius.gameserver.handler.itemhandlers.SoulCrystals;
import com.l2jmobius.gameserver.handler.itemhandlers.SoulShots;
import com.l2jmobius.gameserver.handler.itemhandlers.SpecialXMas;
import com.l2jmobius.gameserver.handler.itemhandlers.SpiritShot;
import com.l2jmobius.gameserver.handler.itemhandlers.SummonItems;
import com.l2jmobius.gameserver.handler.itemhandlers.WorldMap;
import com.l2jmobius.gameserver.handler.skillhandlers.BalanceLife;
import com.l2jmobius.gameserver.handler.skillhandlers.BeastFeed;
import com.l2jmobius.gameserver.handler.skillhandlers.Blow;
import com.l2jmobius.gameserver.handler.skillhandlers.Charge;
import com.l2jmobius.gameserver.handler.skillhandlers.CombatPointHeal;
import com.l2jmobius.gameserver.handler.skillhandlers.Continuous;
import com.l2jmobius.gameserver.handler.skillhandlers.CpDamPercent;
import com.l2jmobius.gameserver.handler.skillhandlers.Craft;
import com.l2jmobius.gameserver.handler.skillhandlers.DeluxeKey;
import com.l2jmobius.gameserver.handler.skillhandlers.Disablers;
import com.l2jmobius.gameserver.handler.skillhandlers.DrainSoul;
import com.l2jmobius.gameserver.handler.skillhandlers.Fishing;
import com.l2jmobius.gameserver.handler.skillhandlers.FishingSkill;
import com.l2jmobius.gameserver.handler.skillhandlers.GetPlayer;
import com.l2jmobius.gameserver.handler.skillhandlers.Harvest;
import com.l2jmobius.gameserver.handler.skillhandlers.Heal;
import com.l2jmobius.gameserver.handler.skillhandlers.ManaDam;
import com.l2jmobius.gameserver.handler.skillhandlers.ManaHeal;
import com.l2jmobius.gameserver.handler.skillhandlers.Mdam;
import com.l2jmobius.gameserver.handler.skillhandlers.Pdam;
import com.l2jmobius.gameserver.handler.skillhandlers.Recall;
import com.l2jmobius.gameserver.handler.skillhandlers.Resurrect;
import com.l2jmobius.gameserver.handler.skillhandlers.Sow;
import com.l2jmobius.gameserver.handler.skillhandlers.Spoil;
import com.l2jmobius.gameserver.handler.skillhandlers.StrSiegeAssault;
import com.l2jmobius.gameserver.handler.skillhandlers.Sweep;
import com.l2jmobius.gameserver.handler.skillhandlers.Unlock;
import com.l2jmobius.gameserver.handler.usercommandhandlers.ChannelDelete;
import com.l2jmobius.gameserver.handler.usercommandhandlers.ChannelLeave;
import com.l2jmobius.gameserver.handler.usercommandhandlers.ChannelListUpdate;
import com.l2jmobius.gameserver.handler.usercommandhandlers.ClanPenalty;
import com.l2jmobius.gameserver.handler.usercommandhandlers.ClanWarsList;
import com.l2jmobius.gameserver.handler.usercommandhandlers.DisMount;
import com.l2jmobius.gameserver.handler.usercommandhandlers.Escape;
import com.l2jmobius.gameserver.handler.usercommandhandlers.Loc;
import com.l2jmobius.gameserver.handler.usercommandhandlers.Mount;
import com.l2jmobius.gameserver.handler.usercommandhandlers.OlympiadStat;
import com.l2jmobius.gameserver.handler.usercommandhandlers.PartyInfo;
import com.l2jmobius.gameserver.handler.usercommandhandlers.Time;
import com.l2jmobius.gameserver.handler.voicedcommandhandlers.TvTCommand;
import com.l2jmobius.gameserver.handler.voicedcommandhandlers.VoiceExperience;
import com.l2jmobius.gameserver.handler.voicedcommandhandlers.stats;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.AuctionManager;
import com.l2jmobius.gameserver.instancemanager.BoatManager;
import com.l2jmobius.gameserver.instancemanager.CastleManager;
import com.l2jmobius.gameserver.instancemanager.CastleManorManager;
import com.l2jmobius.gameserver.instancemanager.ClanHallManager;
import com.l2jmobius.gameserver.instancemanager.DayNightSpawnManager;
import com.l2jmobius.gameserver.instancemanager.DimensionalRiftManager;
import com.l2jmobius.gameserver.instancemanager.FourSepulchersManager;
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
import com.l2jmobius.gameserver.instancemanager.MercTicketManager;
import com.l2jmobius.gameserver.instancemanager.PetitionManager;
import com.l2jmobius.gameserver.instancemanager.QuestManager;
import com.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
import com.l2jmobius.gameserver.instancemanager.SiegeManager;
import com.l2jmobius.gameserver.model.AutoChatHandler;
import com.l2jmobius.gameserver.model.AutoSpawnHandler;
import com.l2jmobius.gameserver.model.EventEngine;
import com.l2jmobius.gameserver.model.L2Manor;
import com.l2jmobius.gameserver.model.L2Multisell;
import com.l2jmobius.gameserver.model.L2PetDataTable;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.PartyMatchRoomList;
import com.l2jmobius.gameserver.model.entity.AutoRewarder;
import com.l2jmobius.gameserver.model.entity.Hero;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.L2GamePacketHandler;
import com.l2jmobius.gameserver.pathfinding.PathFinding;
import com.l2jmobius.gameserver.script.faenor.FaenorScriptEngine;
import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager;
import com.l2jmobius.gameserver.taskmanager.AutoAnnounceTaskManager;
import com.l2jmobius.gameserver.taskmanager.KnownListUpdateTaskManager;
import com.l2jmobius.gameserver.taskmanager.TaskManager;
import com.l2jmobius.gameserver.util.DynamicExtension;
import com.l2jmobius.status.Status;
import com.l2jmobius.util.DeadLockDetector;
import com.l2jmobius.util.IPv4Filter;
/**
* This class ...
* @version $Revision: 1.29.2.15.2.19 $ $Date: 2005/04/05 19:41:23 $
*/
public class GameServer
{
private static final Logger _log = Logger.getLogger(GameServer.class.getName());
private final SelectorThread<L2GameClient> _selectorThread;
private final DeadLockDetector _deadDetectThread;
private final ItemTable _itemTable;
private final NpcTable _npcTable;
private final HennaTable _hennaTable;
private final IdFactory _idFactory;
public static GameServer gameServer;
private final ItemHandler _itemHandler;
private final SkillHandler _skillHandler;
private final AdminCommandHandler _adminCommandHandler;
private final Shutdown _shutdownHandler;
private final UserCommandHandler _userCommandHandler;
private final VoicedCommandHandler _voicedCommandHandler;
private final DoorTable _doorTable;
private final SevenSigns _sevenSignsEngine;
private final AutoChatHandler _autoChatHandler;
private final AutoSpawnHandler _autoSpawnHandler;
private final LoginServerThread _loginThread;
private final HelperBuffTable _helperBuffTable;
public static Status statusServer;
@SuppressWarnings("unused")
private final ThreadPoolManager _threadpools;
public static final Calendar DateTimeServerStarted = Calendar.getInstance();
public long getUsedMemoryMB()
{
return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1048576; // 1024 * 1024 = 1048576
}
public SelectorThread<L2GameClient> getSelectorThread()
{
return _selectorThread;
}
public GameServer() throws Exception
{
final long serverLoadStart = System.currentTimeMillis();
gameServer = this;
_log.finest("used mem:" + getUsedMemoryMB() + "MB");
_idFactory = IdFactory.getInstance();
if (!_idFactory.isInitialized())
{
_log.severe("Could not read object IDs from DB. Please Check Your Data.");
throw new Exception("Could not initialize the ID factory");
}
_threadpools = ThreadPoolManager.getInstance();
new File(Config.DATAPACK_ROOT, "data/clans").mkdirs();
new File(Config.DATAPACK_ROOT, "data/crests").mkdirs();
// load script engines
L2ScriptEngineManager.getInstance();
// start game time control early
GameTimeController.getInstance();
// keep the references of Singletons to prevent garbage collection
CharNameTable.getInstance();
_itemTable = ItemTable.getInstance();
if (!_itemTable.isInitialized())
{
_log.severe("Could not find the extraced files. Please Check Your Data.");
throw new Exception("Could not initialize the item table");
}
ExtractableItemsData.getInstance();
SummonItemsData.getInstance();
TradeController.getInstance();
L2Multisell.getInstance();
SkillTable.getInstance();
// L2EMU_ADD by Rayan. L2J - BigBro
if (Config.ALLOW_NPC_WALKERS)
{
NpcWalkerRoutesTable.getInstance();
}
RecipeController.getInstance();
if (Config.NPC_BUFFER_ENABLED)
{
NpcBufferTable.getInstance();
}
SkillTreeTable.getInstance();
ArmorSetsTable.getInstance();
FishTable.getInstance();
if (Config.SP_BOOK_NEEDED)
{
SkillSpellbookTable.getInstance();
}
CharTemplateTable.getInstance();
NobleSkillTable.getInstance();
// Call to load caches
HtmCache.getInstance();
CrestCache.getInstance();
// forum has to be loaded before clan data, because of last forum id used should have also memo included
if (Config.COMMUNITY_TYPE > 0)
{
ForumsBBSManager.getInstance().initRoot();
}
ClanTable.getInstance();
GeoData.getInstance();
if (Config.GEODATA == 2)
{
PathFinding.getInstance();
}
_npcTable = NpcTable.getInstance();
if (!_npcTable.isInitialized())
{
_log.severe("Could not find the extraced files. Please Check Your Data.");
throw new Exception("Could not initialize the npc table");
}
_hennaTable = HennaTable.getInstance();
if (!_hennaTable.isInitialized())
{
throw new Exception("Could not initialize the Henna Table");
}
HennaTreeTable.getInstance();
if (!_hennaTable.isInitialized())
{
throw new Exception("Could not initialize the Henna Tree Table");
}
_helperBuffTable = HelperBuffTable.getInstance();
if (!_helperBuffTable.isInitialized())
{
throw new Exception("Could not initialize the Helper Buff Table");
}
// Load clan hall data before zone data
ClanHallManager.getInstance();
CastleManager.getInstance();
SiegeManager.getInstance();
TeleportLocationTable.getInstance();
LevelUpData.getInstance();
L2World.getInstance();
ZoneTable.getInstance();
SpawnTable.getInstance();
RaidBossSpawnManager.getInstance();
DayNightSpawnManager.getInstance().notifyChangeMode();
DimensionalRiftManager.getInstance();
GrandBossManager.getInstance();
FourSepulchersManager.getInstance().init();
Announcements.getInstance();
MapRegionTable.getInstance();
EventDroplist.getInstance();
/** Load Manor data */
L2Manor.getInstance();
AuctionManager.getInstance();
BoatManager.getInstance();
CastleManorManager.getInstance();
MercTicketManager.getInstance();
PartyMatchRoomList.getInstance();
PetitionManager.getInstance();
QuestManager.getInstance();
try
{
_log.info("Loading Server Scripts");
final File scripts = new File(Config.DATAPACK_ROOT + "/data/scripts.cfg");
L2ScriptEngineManager.getInstance().executeScriptList(scripts);
}
catch (final Exception ioe)
{
_log.severe("Failed loading scripts.cfg, no script is going to be loaded");
}
QuestManager.getInstance().report();
if (Config.SAVE_DROPPED_ITEM)
{
ItemsOnGroundManager.getInstance();
}
if (Config.AUTODESTROY_ITEM_AFTER > 0)
{
ItemsAutoDestroy.getInstance();
}
MonsterRace.getInstance();
_doorTable = DoorTable.getInstance();
_doorTable.parseData();
StaticObjects.getInstance();
_sevenSignsEngine = SevenSigns.getInstance();
SevenSignsFestival.getInstance();
_autoSpawnHandler = AutoSpawnHandler.getInstance();
_autoChatHandler = AutoChatHandler.getInstance();
// Spawn the Orators/Preachers if in the Seal Validation period.
_sevenSignsEngine.spawnSevenSignsNPC();
Olympiad.getInstance();
Hero.getInstance();
FaenorScriptEngine.getInstance();
_log.config("AutoChatHandler: Loaded " + _autoChatHandler.size() + " handlers in total.");
_log.config("AutoSpawnHandler: Loaded " + _autoSpawnHandler.size() + " handlers in total.");
_itemHandler = ItemHandler.getInstance();
_itemHandler.registerItemHandler(new ScrollOfEscape());
_itemHandler.registerItemHandler(new ScrollOfResurrection());
_itemHandler.registerItemHandler(new SoulShots());
_itemHandler.registerItemHandler(new SpecialXMas());
_itemHandler.registerItemHandler(new SpiritShot());
_itemHandler.registerItemHandler(new BlessedSpiritShot());
_itemHandler.registerItemHandler(new BeastSoulShot());
_itemHandler.registerItemHandler(new BeastSpiritShot());
_itemHandler.registerItemHandler(new ChestKey());
_itemHandler.registerItemHandler(new WorldMap());
_itemHandler.registerItemHandler(new PetFood());
_itemHandler.registerItemHandler(new Potions());
_itemHandler.registerItemHandler(new Recipes());
_itemHandler.registerItemHandler(new RollingDice());
_itemHandler.registerItemHandler(new EnchantScrolls());
_itemHandler.registerItemHandler(new EnergyStone());
_itemHandler.registerItemHandler(new Book());
_itemHandler.registerItemHandler(new Remedy());
_itemHandler.registerItemHandler(new Scrolls());
_itemHandler.registerItemHandler(new CrystalCarol());
_itemHandler.registerItemHandler(new SoulCrystals());
_itemHandler.registerItemHandler(new SevenSignsRecord());
_itemHandler.registerItemHandler(new CharChangePotions());
_itemHandler.registerItemHandler(new Firework());
_itemHandler.registerItemHandler(new Seed());
_itemHandler.registerItemHandler(new Harvester());
_itemHandler.registerItemHandler(new MercTicket());
_itemHandler.registerItemHandler(new FishShots());
_itemHandler.registerItemHandler(new ExtractableItems());
_itemHandler.registerItemHandler(new SummonItems());
_itemHandler.registerItemHandler(new BeastSpice());
_log.config("ItemHandler: Loaded " + _itemHandler.size() + " handlers.");
_skillHandler = SkillHandler.getInstance();
_skillHandler.registerSkillHandler(new Blow());
_skillHandler.registerSkillHandler(new Pdam());
_skillHandler.registerSkillHandler(new Mdam());
_skillHandler.registerSkillHandler(new Heal());
_skillHandler.registerSkillHandler(new CombatPointHeal());
_skillHandler.registerSkillHandler(new ManaDam());
_skillHandler.registerSkillHandler(new ManaHeal());
_skillHandler.registerSkillHandler(new BalanceLife());
_skillHandler.registerSkillHandler(new Charge());
_skillHandler.registerSkillHandler(new Continuous());
_skillHandler.registerSkillHandler(new CpDamPercent());
_skillHandler.registerSkillHandler(new Resurrect());
_skillHandler.registerSkillHandler(new Spoil());
_skillHandler.registerSkillHandler(new Sweep());
_skillHandler.registerSkillHandler(new StrSiegeAssault());
_skillHandler.registerSkillHandler(new Disablers());
_skillHandler.registerSkillHandler(new Recall());
_skillHandler.registerSkillHandler(new Unlock());
_skillHandler.registerSkillHandler(new DrainSoul());
_skillHandler.registerSkillHandler(new Craft());
_skillHandler.registerSkillHandler(new Fishing());
_skillHandler.registerSkillHandler(new FishingSkill());
_skillHandler.registerSkillHandler(new Sow());
_skillHandler.registerSkillHandler(new Harvest());
_skillHandler.registerSkillHandler(new DeluxeKey());
_skillHandler.registerSkillHandler(new BeastFeed());
_skillHandler.registerSkillHandler(new GetPlayer());
_log.config("SkillHandler: Loaded " + _skillHandler.size() + " handlers.");
_adminCommandHandler = AdminCommandHandler.getInstance();
_adminCommandHandler.registerAdminCommandHandler(new AdminAdmin());
_adminCommandHandler.registerAdminCommandHandler(new AdminInvul());
_adminCommandHandler.registerAdminCommandHandler(new AdminDelete());
_adminCommandHandler.registerAdminCommandHandler(new AdminKill());
_adminCommandHandler.registerAdminCommandHandler(new AdminTarget());
_adminCommandHandler.registerAdminCommandHandler(new AdminShop());
_adminCommandHandler.registerAdminCommandHandler(new AdminAnnouncements());
_adminCommandHandler.registerAdminCommandHandler(new AdminCreateItem());
_adminCommandHandler.registerAdminCommandHandler(new AdminHeal());
_adminCommandHandler.registerAdminCommandHandler(new AdminHelpPage());
_adminCommandHandler.registerAdminCommandHandler(new AdminShutdown());
_adminCommandHandler.registerAdminCommandHandler(new AdminSpawn());
_adminCommandHandler.registerAdminCommandHandler(new AdminSkill());
_adminCommandHandler.registerAdminCommandHandler(new AdminExpSp());
_adminCommandHandler.registerAdminCommandHandler(new AdminEventEngine());
_adminCommandHandler.registerAdminCommandHandler(new AdminGmChat());
_adminCommandHandler.registerAdminCommandHandler(new AdminEditChar());
_adminCommandHandler.registerAdminCommandHandler(new AdminGm());
_adminCommandHandler.registerAdminCommandHandler(new AdminTeleport());
_adminCommandHandler.registerAdminCommandHandler(new AdminRepairChar());
_adminCommandHandler.registerAdminCommandHandler(new AdminChangeAccessLevel());
_adminCommandHandler.registerAdminCommandHandler(new AdminBan());
_adminCommandHandler.registerAdminCommandHandler(new AdminPolymorph());
_adminCommandHandler.registerAdminCommandHandler(new AdminBanChat());
_adminCommandHandler.registerAdminCommandHandler(new AdminKick());
_adminCommandHandler.registerAdminCommandHandler(new AdminDisconnect());
_adminCommandHandler.registerAdminCommandHandler(new AdminMonsterRace());
_adminCommandHandler.registerAdminCommandHandler(new AdminEditNpc());
_adminCommandHandler.registerAdminCommandHandler(new AdminFightCalculator());
_adminCommandHandler.registerAdminCommandHandler(new AdminMenu());
_adminCommandHandler.registerAdminCommandHandler(new AdminSiege());
_adminCommandHandler.registerAdminCommandHandler(new AdminPathNode());
_adminCommandHandler.registerAdminCommandHandler(new AdminPetition());
_adminCommandHandler.registerAdminCommandHandler(new AdminPForge());
_adminCommandHandler.registerAdminCommandHandler(new AdminBBS());
_adminCommandHandler.registerAdminCommandHandler(new AdminEffects());
_adminCommandHandler.registerAdminCommandHandler(new AdminDoorControl());
_adminCommandHandler.registerAdminCommandHandler(new AdminTest());
_adminCommandHandler.registerAdminCommandHandler(new AdminEnchant());
_adminCommandHandler.registerAdminCommandHandler(new AdminMobGroup());
_adminCommandHandler.registerAdminCommandHandler(new AdminRes());
_adminCommandHandler.registerAdminCommandHandler(new AdminMammon());
_adminCommandHandler.registerAdminCommandHandler(new AdminUnblockIp());
_adminCommandHandler.registerAdminCommandHandler(new AdminPledge());
_adminCommandHandler.registerAdminCommandHandler(new AdminRideWyvern());
_adminCommandHandler.registerAdminCommandHandler(new AdminLogin());
_adminCommandHandler.registerAdminCommandHandler(new AdminCache());
_adminCommandHandler.registerAdminCommandHandler(new AdminLevel());
_adminCommandHandler.registerAdminCommandHandler(new AdminQuest());
_adminCommandHandler.registerAdminCommandHandler(new AdminZone());
_adminCommandHandler.registerAdminCommandHandler(new AdminGeodata());
_adminCommandHandler.registerAdminCommandHandler(new AdminGeoEditor());
_adminCommandHandler.registerAdminCommandHandler(new AdminManor());
// _adminCommandHandler.registerAdminCommandHandler(new AdminRadar());
_log.config("AdminCommandHandler: Loaded " + _adminCommandHandler.size() + " handlers.");
_userCommandHandler = UserCommandHandler.getInstance();
_userCommandHandler.registerUserCommandHandler(new ClanPenalty());
_userCommandHandler.registerUserCommandHandler(new ClanWarsList());
_userCommandHandler.registerUserCommandHandler(new DisMount());
_userCommandHandler.registerUserCommandHandler(new Escape());
_userCommandHandler.registerUserCommandHandler(new Loc());
_userCommandHandler.registerUserCommandHandler(new Mount());
_userCommandHandler.registerUserCommandHandler(new OlympiadStat());
_userCommandHandler.registerUserCommandHandler(new PartyInfo());
_userCommandHandler.registerUserCommandHandler(new Time());
_userCommandHandler.registerUserCommandHandler(new ChannelLeave());
_userCommandHandler.registerUserCommandHandler(new ChannelDelete());
_userCommandHandler.registerUserCommandHandler(new ChannelListUpdate());
_log.config("UserCommandHandler: Loaded " + _userCommandHandler.size() + " handlers.");
_voicedCommandHandler = VoicedCommandHandler.getInstance();
_voicedCommandHandler.registerVoicedCommandHandler(new stats());
if (Config.Boost_EXP_COMMAND)
{
_voicedCommandHandler.registerVoicedCommandHandler(new VoiceExperience());
}
_voicedCommandHandler.registerVoicedCommandHandler(new TvTCommand());
_log.config("VoicedCommandHandler: Loaded " + _voicedCommandHandler.size() + " handlers.");
TaskManager.getInstance();
GmListTable.getInstance();
// read pet stats from db
L2PetDataTable.getInstance().loadPetsData();
if (Config.ACCEPT_GEOEDITOR_CONN)
{
GeoEditorListener.getInstance();
}
_shutdownHandler = Shutdown.getInstance();
Runtime.getRuntime().addShutdownHook(_shutdownHandler);
try
{
_doorTable.getDoor(24190001).openMe();
_doorTable.getDoor(24190002).openMe();
_doorTable.getDoor(24190003).openMe();
_doorTable.getDoor(24190004).openMe();
_doorTable.getDoor(23180001).openMe();
_doorTable.getDoor(23180002).openMe();
_doorTable.getDoor(23180003).openMe();
_doorTable.getDoor(23180004).openMe();
_doorTable.getDoor(23180005).openMe();
_doorTable.getDoor(23180006).openMe();
_doorTable.checkAutoOpen();
}
catch (final NullPointerException e)
{
_log.warning("There is an error in your Door.csv file. Please update that file.");
if (Config.DEBUG)
{
e.printStackTrace();
}
}
_log.config("IdFactory: Free ObjectID's remaining: " + IdFactory.getInstance().size());
// initialize the dynamic extension loader
try
{
DynamicExtension.getInstance();
}
catch (final Exception ex)
{
_log.log(Level.WARNING, "DynamicExtension could not be loaded and initialized", ex);
}
if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)
{
OfflineTradersTable.restoreOfflineTraders();
}
if (Config.ALLOW_AUTO_REWARDER)
{
AutoRewarder.load();
}
// Start Event Engine
EventEngine.load();
KnownListUpdateTaskManager.getInstance();
if (Config.DEADLOCK_DETECTOR)
{
_deadDetectThread = new DeadLockDetector();
_deadDetectThread.setDaemon(true);
_deadDetectThread.start();
}
else
{
_deadDetectThread = null;
}
System.gc();
// maxMemory is the upper limit the JVM can use, totalMemory the size of the current allocation pool, freeMemory the unused memory in the allocation pool
final long freeMem = ((Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory()) + Runtime.getRuntime().freeMemory()) / 1048576; // 1024 * 1024 = 1048576
final long totalMem = Runtime.getRuntime().maxMemory() / 1048576;
_log.info("GameServer Started, free memory " + freeMem + " Mb of " + totalMem + " Mb");
_loginThread = LoginServerThread.getInstance();
_loginThread.start();
final SelectorConfig sc = new SelectorConfig();
sc.MAX_READ_PER_PASS = Config.MMO_MAX_READ_PER_PASS;
sc.MAX_SEND_PER_PASS = Config.MMO_MAX_SEND_PER_PASS;
sc.SLEEP_TIME = Config.MMO_SELECTOR_SLEEP_TIME;
sc.HELPER_BUFFER_COUNT = Config.MMO_HELPER_BUFFER_COUNT;
final L2GamePacketHandler gph = new L2GamePacketHandler();
_selectorThread = new SelectorThread<>(sc, gph, gph, gph, new IPv4Filter());
InetAddress bindAddress = null;
if (!Config.GAMESERVER_HOSTNAME.equals("*"))
{
try
{
bindAddress = InetAddress.getByName(Config.GAMESERVER_HOSTNAME);
}
catch (final UnknownHostException e1)
{
_log.log(Level.SEVERE, "WARNING: The GameServer bind address is invalid, using all avaliable IPs. Reason: " + e1.getMessage(), e1);
}
}
try
{
_selectorThread.openServerSocket(bindAddress, Config.PORT_GAME);
}
catch (final IOException e)
{
_log.log(Level.SEVERE, "FATAL: Failed to open server socket. Reason: " + e.getMessage(), e);
System.exit(1);
}
_selectorThread.start();
_log.config("Maximum Number of Connected Players: " + Config.MAXIMUM_ONLINE_USERS);
_log.log(Level.INFO, getClass().getSimpleName() + ": Server loaded in " + ((System.currentTimeMillis() - serverLoadStart) / 1000) + " seconds.");
AutoAnnounceTaskManager.getInstance();
}
public static void main(String[] args) throws Exception
{
Server.SERVER_MODE = Server.MODE_GAMESERVER;
// Local Constants
final String LOG_FOLDER = "log"; // Name of folder for log file
final String LOG_NAME = "./log.cfg"; // Name of log file
/*** Main ***/
// Create log folder
final File logFolder = new File(Config.DATAPACK_ROOT, LOG_FOLDER);
logFolder.mkdir();
// Create input stream for log file -- or store file data into memory
try (InputStream is = new FileInputStream(new File(LOG_NAME)))
{
LogManager.getLogManager().readConfiguration(is);
}
// Initialize config
Config.load();
L2DatabaseFactory.getInstance();
gameServer = new GameServer();
if (Config.IS_TELNET_ENABLED)
{
statusServer = new Status(Server.SERVER_MODE);
statusServer.start();
}
else
{
System.out.println("Telnet server is currently disabled.");
}
}
}

View File

@@ -0,0 +1,283 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.ai.CtrlEvent;
import com.l2jmobius.gameserver.instancemanager.DayNightSpawnManager;
import com.l2jmobius.gameserver.model.L2Character;
import javolution.util.FastList;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.1.4.8 $ $Date: 2005/04/06 16:13:24 $
*/
@SuppressWarnings("rawtypes")
public class GameTimeController
{
static final Logger _log = Logger.getLogger(GameTimeController.class.getName());
public static final int TICKS_PER_SECOND = 10;
public static final int MILLIS_IN_TICK = 1000 / TICKS_PER_SECOND;
private static GameTimeController _instance = new GameTimeController();
protected static int _gameTicks;
protected static long _gameStartTime;
protected static boolean _isNight = false;
private static Map<Integer, L2Character> _movingObjects = new FastMap<Integer, L2Character>().shared();
protected static TimerThread _timer;
private final ScheduledFuture _timerWatcher;
/**
* one ingame day is 240 real minutes
* @return
*/
public static GameTimeController getInstance()
{
return _instance;
}
private GameTimeController()
{
_gameStartTime = System.currentTimeMillis() - 3600000; // offset so that the server starts a day begin
_gameTicks = 3600000 / MILLIS_IN_TICK; // offset so that the server starts a day begin
_timer = new TimerThread();
_timer.start();
_timerWatcher = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new TimerWatcher(), 0, 1000);
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new BroadcastSunState(), 20000, 600000);
}
public boolean isNowNight()
{
return _isNight;
}
public int getGameTime()
{
return (_gameTicks / (TICKS_PER_SECOND * 10));
}
public static int getGameTicks()
{
return _gameTicks;
}
/**
* Add a L2Character to movingObjects of GameTimeController.<BR>
* <BR>
* <B><U> Concept</U> :</B><BR>
* <BR>
* All L2Character in movement are identified in <B>movingObjects</B> of GameTimeController.<BR>
* <BR>
* @param cha The L2Character to add to movingObjects of GameTimeController
*/
public void registerMovingObject(L2Character cha)
{
if (cha == null)
{
return;
}
if (!_movingObjects.containsKey(cha.getObjectId()))
{
_movingObjects.put(cha.getObjectId(), cha);
}
}
/**
* Move all L2Characters contained in movingObjects of GameTimeController.<BR>
* <BR>
* <B><U> Concept</U> :</B><BR>
* <BR>
* All L2Character in movement are identified in <B>movingObjects</B> of GameTimeController.<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Update the position of each L2Character</li>
* <li>If movement is finished, the L2Character is removed from movingObjects</li>
* <li>Create a task to update the _knownObject and _knowPlayers of each L2Character that finished its movement and of their already known L2Object then notify AI with EVT_ARRIVED</li><BR>
* <BR>
*/
protected void moveObjects()
{
// Create an FastList to contain all L2Character that are arrived to
// destination
FastList<L2Character> ended = null;
// Go throw the table containing L2Character in movement
for (final L2Character ch : _movingObjects.values())
{
// If movement is finished, the L2Character is removed from
// movingObjects and added to the ArrayList ended
if (ch != null)
{
if (ch.updatePosition(_gameTicks))
{
if (ended == null)
{
ended = new FastList<>();
}
ended.add(ch);
}
}
}
if (ended != null)
{
_movingObjects.values().removeAll(ended);
for (final L2Character ch : ended)
{
if (ch != null)
{
ThreadPoolManager.getInstance().executeTask(new MovingObjectArrived(ch));
}
}
ended.clear();
}
}
public void stopTimer()
{
_timerWatcher.cancel(true);
_timer.interrupt();
}
class TimerThread extends Thread
{
protected Exception _error;
public TimerThread()
{
super("GameTimeController");
setDaemon(true);
setPriority(MAX_PRIORITY);
_error = null;
}
@Override
public void run()
{
try
{
for (;;)
{
final int _oldTicks = _gameTicks; // save old ticks value to avoid moving objects 2x in same tick
long runtime = System.currentTimeMillis() - _gameStartTime; // from server boot to now
_gameTicks = (int) (runtime / MILLIS_IN_TICK); // new ticks value (ticks now)
if (_oldTicks != _gameTicks)
{
moveObjects(); // Runs possibly too often
}
runtime = (System.currentTimeMillis() - _gameStartTime) - runtime;
// calculate sleep time... time needed to next tick minus time it takes to call moveObjects()
final int sleepTime = (1 + MILLIS_IN_TICK) - (((int) runtime) % MILLIS_IN_TICK);
// _log.finest("TICK: "+_gameTicks);
sleep(sleepTime); // hope other threads will have much more cpu time available now
// SelectorThread most of all
}
}
catch (final Exception e)
{
_error = e;
}
}
}
class TimerWatcher implements Runnable
{
@Override
public void run()
{
if (!_timer.isAlive())
{
final String time = (new SimpleDateFormat("HH:mm:ss")).format(new Date());
_log.warning(time + " TimerThread stop with following error. restart it.");
if (_timer._error != null)
{
_timer._error.printStackTrace();
}
_timer = new TimerThread();
_timer.start();
}
}
}
/**
* Update the _knownObject and _knowPlayers of each L2Character that finished its movement and of their already known L2Object then notify AI with EVT_ARRIVED.<BR>
* <BR>
*/
class MovingObjectArrived implements Runnable
{
private final L2Character _ended;
MovingObjectArrived(L2Character ended)
{
_ended = ended;
}
@Override
public void run()
{
try
{
if (_ended.hasAI())
{
_ended.getAI().notifyEvent(CtrlEvent.EVT_ARRIVED);
}
}
catch (final NullPointerException e)
{
e.printStackTrace();
}
}
}
class BroadcastSunState implements Runnable
{
@Override
public void run()
{
final int h = (getGameTime() / 60) % 24; // Time in hour
final boolean tempIsNight = (h < 6);
if (tempIsNight != _isNight) // If diff day/night state
{
_isNight = tempIsNight; // Set current day/night varible to value of temp varible
DayNightSpawnManager.getInstance().notifyChangeMode();
}
}
}
}

View File

@@ -0,0 +1,577 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.datatables.DoorTable;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.util.GeoUtils;
import com.l2jmobius.gameserver.util.LinePointIterator;
import com.l2jmobius.gameserver.util.LinePointIterator3D;
import com.l2jserver.gameserver.geoengine.Direction;
import com.l2jserver.gameserver.geoengine.NullDriver;
import com.l2jserver.gameserver.geoengine.abstraction.IGeoDriver;
/**
* @author -Nemesiss-, FBIagent
*/
public class GeoData implements IGeoDriver
{
private static Logger LOGGER = Logger.getLogger(GeoData.class.getName());
private static final int ELEVATED_SEE_OVER_DISTANCE = 2;
private static final int MAX_SEE_OVER_HEIGHT = 48;
private final IGeoDriver _driver;
private static GeoData _instance;
public static GeoData getInstance()
{
if (_instance == null)
{
_instance = new GeoData();
}
return _instance;
}
protected GeoData()
{
if (Config.GEODATA > 0)
{
IGeoDriver driver = null;
try
{
final Class<?> cls = Class.forName(Config.GEODATA_DRIVER);
if (!IGeoDriver.class.isAssignableFrom(cls))
{
throw new ClassCastException("Geodata driver class needs to implement IGeoDriver!");
}
final Constructor<?> ctor = cls.getConstructor(Properties.class);
final Properties props = new Properties();
try (FileInputStream fis = new FileInputStream(Paths.get("config", "GeoDriver.ini").toString()))
{
props.load(fis);
}
driver = (IGeoDriver) ctor.newInstance(props);
}
catch (final Exception ex)
{
LOGGER.log(Level.SEVERE, "Failed to load geodata driver!", ex);
System.exit(1);
}
// we do it this way so it's predictable for the compiler
_driver = driver;
}
else
{
_driver = new NullDriver(null);
}
}
public boolean isNullDriver()
{
return _driver instanceof NullDriver;
}
@Override
public int getGeoX(int worldX)
{
return _driver.getGeoX(worldX);
}
@Override
public int getGeoY(int worldY)
{
return _driver.getGeoY(worldY);
}
@Override
public int getWorldX(int geoX)
{
return _driver.getWorldX(geoX);
}
@Override
public int getWorldY(int geoY)
{
return _driver.getWorldY(geoY);
}
@Override
public boolean hasGeoPos(int geoX, int geoY)
{
return _driver.hasGeoPos(geoX, geoY);
}
@Override
public int getNearestZ(int geoX, int geoY, int worldZ)
{
return _driver.getNearestZ(geoX, geoY, worldZ);
}
@Override
public int getNextLowerZ(int geoX, int geoY, int worldZ)
{
return _driver.getNextLowerZ(geoX, geoY, worldZ);
}
@Override
public int getNextHigherZ(int geoX, int geoY, int worldZ)
{
return _driver.getNextHigherZ(geoX, geoY, worldZ);
}
@Override
public boolean canEnterNeighbors(int geoX, int geoY, int worldZ, Direction first, Direction... more)
{
return _driver.canEnterNeighbors(geoX, geoY, worldZ, first, more);
}
@Override
public boolean canEnterAllNeighbors(int geoX, int geoY, int worldZ)
{
return _driver.canEnterAllNeighbors(geoX, geoY, worldZ);
}
/**
* @param x
* @param y
* @param z
* @return Nearles Z
*/
public int getHeight(int x, int y, int z)
{
return getNearestZ(getGeoX(x), getGeoY(y), z);
}
/**
* @param x
* @param y
* @param zmin
* @param zmax
* @return
*/
public int getSpawnHeight(int x, int y, int zmin, int zmax)
{
// + 30, defend against defective geodata and invalid spawn z :(
return getNextLowerZ(getGeoX(x), getGeoY(y), zmax + 30);
}
private int getLosGeoZ(int prevX, int prevY, int prevGeoZ, int curX, int curY, Direction dir)
{
boolean can = true;
switch (dir)
{
case NORTH_EAST:
can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.NORTH);
break;
case NORTH_WEST:
can = canEnterNeighbors(prevX, prevY - 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.NORTH);
break;
case SOUTH_EAST:
can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevGeoZ, Direction.SOUTH);
break;
case SOUTH_WEST:
can = canEnterNeighbors(prevX, prevY + 1, prevGeoZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevGeoZ, Direction.SOUTH);
break;
}
if (can && canEnterNeighbors(prevX, prevY, prevGeoZ, dir))
{
return getNearestZ(curX, curY, prevGeoZ);
}
return getNextHigherZ(curX, curY, prevGeoZ);
}
/**
* Can see target. Doors as target always return true. Checks doors between.
* @param cha
* @param target
* @return True if cha can see target (LOS)
*/
public boolean canSeeTarget(L2Object cha, L2Object target)
{
if (target instanceof L2DoorInstance)
{
// can always see doors :o
return true;
}
if (DoorTable.getInstance().checkIfDoorsBetween(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ()))
{
return false;
}
return canSeeTarget(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ());
}
/**
* Can see target. Does not check doors between.
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @param tx the target's x coordinate
* @param ty the target's y coordinate
* @param tz the target's z coordinate
* @return {@code true} if there is line of sight between the given coordinate sets, {@code false} otherwise
*/
public boolean canSeeTarget(int x, int y, int z, int tx, int ty, int tz)
{
int geoX = getGeoX(x);
int geoY = getGeoY(y);
int tGeoX = getGeoX(tx);
int tGeoY = getGeoY(ty);
z = getNearestZ(geoX, geoY, z);
tz = getNearestZ(tGeoX, tGeoY, tz);
if ((geoX == tGeoX) && (geoY == tGeoY))
{
if (hasGeoPos(tGeoX, tGeoY))
{
return z == tz;
}
return true;
}
if (tz > z)
{
int tmp = tx;
tx = x;
x = tmp;
tmp = ty;
ty = y;
y = tmp;
tmp = tz;
tz = z;
z = tmp;
tmp = tGeoX;
tGeoX = geoX;
geoX = tmp;
tmp = tGeoY;
tGeoY = geoY;
geoY = tmp;
}
final LinePointIterator3D pointIter = new LinePointIterator3D(geoX, geoY, z, tGeoX, tGeoY, tz);
// first point is guaranteed to be available, skip it, we can always see our own position
pointIter.next();
int prevX = pointIter.x();
int prevY = pointIter.y();
final int prevZ = pointIter.z();
int prevGeoZ = prevZ;
int ptIndex = 0;
while (pointIter.next())
{
final int curX = pointIter.x();
final int curY = pointIter.y();
if ((curX == prevX) && (curY == prevY))
{
continue;
}
final int beeCurZ = pointIter.z();
int curGeoZ = prevGeoZ;
// the current position has geodata
if (hasGeoPos(curX, curY))
{
final int beeCurGeoZ = getNearestZ(curX, curY, beeCurZ);
final Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
curGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, curX, curY, dir);
int maxHeight;
if (ptIndex < ELEVATED_SEE_OVER_DISTANCE)
{
maxHeight = z + MAX_SEE_OVER_HEIGHT;
}
else
{
maxHeight = beeCurZ + MAX_SEE_OVER_HEIGHT;
}
boolean canSeeThrough = false;
if ((curGeoZ <= maxHeight) && (curGeoZ <= beeCurGeoZ))
{
switch (dir)
{
case NORTH_EAST:
{
final int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Direction.EAST);
final int eastGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX + 1, prevY, Direction.NORTH);
canSeeThrough = (northGeoZ <= maxHeight) && (eastGeoZ <= maxHeight) && (northGeoZ <= getNearestZ(prevX, prevY - 1, beeCurZ)) && (eastGeoZ <= getNearestZ(prevX + 1, prevY, beeCurZ));
break;
}
case NORTH_WEST:
{
final int northGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY - 1, Direction.WEST);
final int westGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX - 1, prevY, Direction.NORTH);
canSeeThrough = (northGeoZ <= maxHeight) && (westGeoZ <= maxHeight) && (northGeoZ <= getNearestZ(prevX, prevY - 1, beeCurZ)) && (westGeoZ <= getNearestZ(prevX - 1, prevY, beeCurZ));
break;
}
case SOUTH_EAST:
{
final int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Direction.EAST);
final int eastGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX + 1, prevY, Direction.SOUTH);
canSeeThrough = (southGeoZ <= maxHeight) && (eastGeoZ <= maxHeight) && (southGeoZ <= getNearestZ(prevX, prevY + 1, beeCurZ)) && (eastGeoZ <= getNearestZ(prevX + 1, prevY, beeCurZ));
break;
}
case SOUTH_WEST:
{
final int southGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX, prevY + 1, Direction.WEST);
final int westGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, prevX - 1, prevY, Direction.SOUTH);
canSeeThrough = (southGeoZ <= maxHeight) && (westGeoZ <= maxHeight) && (southGeoZ <= getNearestZ(prevX, prevY + 1, beeCurZ)) && (westGeoZ <= getNearestZ(prevX - 1, prevY, beeCurZ));
break;
}
default:
{
canSeeThrough = true;
break;
}
}
}
if (!canSeeThrough)
{
return false;
}
}
prevX = curX;
prevY = curY;
prevGeoZ = curGeoZ;
++ptIndex;
}
return true;
}
/**
* @param x
* @param y
* @param z
* @param tx
* @param ty
* @param tz
* @return Last Location (x,y,z) where player can walk - just before wall
*/
public Location moveCheck(int x, int y, int z, int tx, int ty, int tz)
{
final int geoX = getGeoX(x);
final int geoY = getGeoY(y);
z = getNearestZ(geoX, geoY, z);
final int tGeoX = getGeoX(tx);
final int tGeoY = getGeoY(ty);
tz = getNearestZ(tGeoX, tGeoY, tz);
if (DoorTable.getInstance().checkIfDoorsBetween(x, y, z, tx, ty, tz))
{
return new Location(x, y, getHeight(x, y, z));
}
final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
// first point is guaranteed to be available
pointIter.next();
int prevX = pointIter.x();
int prevY = pointIter.y();
int prevZ = z;
while (pointIter.next())
{
final int curX = pointIter.x();
final int curY = pointIter.y();
final int curZ = getNearestZ(curX, curY, prevZ);
if (hasGeoPos(prevX, prevY))
{
final Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
boolean canEnter = false;
if (canEnterNeighbors(prevX, prevY, prevZ, dir))
{
// check diagonal movement
switch (dir)
{
case NORTH_EAST:
canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.NORTH);
break;
case NORTH_WEST:
canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.NORTH);
break;
case SOUTH_EAST:
canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.SOUTH);
break;
case SOUTH_WEST:
canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.SOUTH);
break;
default:
canEnter = true;
break;
}
}
if (!canEnter)
{
// can't move, return previous location
return new Location(getWorldX(prevX), getWorldY(prevY), prevZ);
}
}
prevX = curX;
prevY = curY;
prevZ = curZ;
}
if (hasGeoPos(prevX, prevY) && (prevZ != tz))
{
// different floors, return start location
return new Location(x, y, z);
}
return new Location(tx, ty, tz);
}
public int traceTerrainZ(int x, int y, int z, int tx, int ty)
{
final int geoX = getGeoX(x);
final int geoY = getGeoY(y);
z = getNearestZ(geoX, geoY, z);
final int tGeoX = getGeoX(tx);
final int tGeoY = getGeoY(ty);
final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
// first point is guaranteed to be available
pointIter.next();
int prevZ = z;
while (pointIter.next())
{
final int curX = pointIter.x();
final int curY = pointIter.y();
final int curZ = getNearestZ(curX, curY, prevZ);
prevZ = curZ;
}
return prevZ;
}
/**
* Checks if its possible to move from one location to another.
* @param fromX the X coordinate to start checking from
* @param fromY the Y coordinate to start checking from
* @param fromZ the Z coordinate to start checking from
* @param toX the X coordinate to end checking at
* @param toY the Y coordinate to end checking at
* @param toZ the Z coordinate to end checking at
* @return {@code true} if the character at start coordinates can move to end coordinates, {@code false} otherwise
*/
public boolean canMove(int fromX, int fromY, int fromZ, int toX, int toY, int toZ)
{
final int geoX = getGeoX(fromX);
final int geoY = getGeoY(fromY);
fromZ = getNearestZ(geoX, geoY, fromZ);
final int tGeoX = getGeoX(toX);
final int tGeoY = getGeoY(toY);
toZ = getNearestZ(tGeoX, tGeoY, toZ);
if (DoorTable.getInstance().checkIfDoorsBetween(fromX, fromY, fromZ, toX, toY, toZ))
{
return false;
}
final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
// first point is guaranteed to be available
pointIter.next();
int prevX = pointIter.x();
int prevY = pointIter.y();
int prevZ = fromZ;
while (pointIter.next())
{
final int curX = pointIter.x();
final int curY = pointIter.y();
final int curZ = getNearestZ(curX, curY, prevZ);
if (hasGeoPos(prevX, prevY))
{
final Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
boolean canEnter = false;
if (canEnterNeighbors(prevX, prevY, prevZ, dir))
{
// check diagonal movement
switch (dir)
{
case NORTH_EAST:
canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.NORTH);
break;
case NORTH_WEST:
canEnter = canEnterNeighbors(prevX, prevY - 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.NORTH);
break;
case SOUTH_EAST:
canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.EAST) && canEnterNeighbors(prevX + 1, prevY, prevZ, Direction.SOUTH);
break;
case SOUTH_WEST:
canEnter = canEnterNeighbors(prevX, prevY + 1, prevZ, Direction.WEST) && canEnterNeighbors(prevX - 1, prevY, prevZ, Direction.SOUTH);
break;
default:
canEnter = true;
break;
}
}
if (!canEnter)
{
return false;
}
}
prevX = curX;
prevY = curY;
prevZ = curZ;
}
if (hasGeoPos(prevX, prevY) && (prevZ != toZ))
{
// different floors
return false;
}
return true;
}
public boolean hasGeo(int x, int y)
{
return hasGeoPos(getGeoX(x), getGeoY(y));
}
}

View File

@@ -0,0 +1,35 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import com.l2jmobius.gameserver.templates.L2Item;
import com.l2jmobius.gameserver.templates.StatsSet;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
*/
@SuppressWarnings("rawtypes")
public class Item
{
public int id;
public Enum type;
public String name;
public StatsSet set;
public int currentLevel;
public L2Item item;
}

View File

@@ -0,0 +1,112 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.util.List;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
import com.l2jmobius.gameserver.model.L2ItemInstance;
import com.l2jmobius.gameserver.model.L2World;
import javolution.util.FastList;
public class ItemsAutoDestroy
{
protected static Logger _log = Logger.getLogger("ItemsAutoDestroy");
private static ItemsAutoDestroy _instance;
protected List<L2ItemInstance> _items = null;
protected static long _sleep;
private ItemsAutoDestroy()
{
_items = new FastList<>();
_sleep = Config.AUTODESTROY_ITEM_AFTER * 1000;
if (_sleep == 0)
{
_sleep = 3600000;
}
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckItemsForDestroy(), 5000, 5000);
}
public static ItemsAutoDestroy getInstance()
{
if (_instance == null)
{
System.out.println("Initializing ItemsAutoDestroy.");
_instance = new ItemsAutoDestroy();
}
return _instance;
}
public synchronized void addItem(L2ItemInstance item)
{
item.setDropTime(System.currentTimeMillis());
_items.add(item);
}
public synchronized void removeItems()
{
if (Config.DEBUG)
{
_log.info("[ItemsAutoDestroy] : " + _items.size() + " items to check.");
}
if (_items.isEmpty())
{
return;
}
final long curtime = System.currentTimeMillis();
for (final L2ItemInstance item : _items)
{
if ((item == null) || (item.getDropTime() == 0) || (item.getLocation() != L2ItemInstance.ItemLocation.VOID))
{
_items.remove(item);
}
else
{
if ((curtime - item.getDropTime()) > _sleep)
{
L2World.getInstance().removeVisibleObject(item, item.getWorldRegion());
L2World.getInstance().removeObject(item);
_items.remove(item);
if (Config.SAVE_DROPPED_ITEM)
{
ItemsOnGroundManager.getInstance().removeObject(item);
}
}
}
}
if (Config.DEBUG)
{
_log.info("[ItemsAutoDestroy] : " + _items.size() + " items remaining.");
}
}
protected class CheckItemsForDestroy extends Thread
{
@Override
public void run()
{
removeItems();
}
}
}

View File

@@ -0,0 +1,697 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.L2GameClient.GameClientState;
import com.l2jmobius.gameserver.network.gameserverpackets.AuthRequest;
import com.l2jmobius.gameserver.network.gameserverpackets.BlowFishKey;
import com.l2jmobius.gameserver.network.gameserverpackets.ChangeAccessLevel;
import com.l2jmobius.gameserver.network.gameserverpackets.GameServerBasePacket;
import com.l2jmobius.gameserver.network.gameserverpackets.PlayerAuthRequest;
import com.l2jmobius.gameserver.network.gameserverpackets.PlayerInGame;
import com.l2jmobius.gameserver.network.gameserverpackets.PlayerLogout;
import com.l2jmobius.gameserver.network.gameserverpackets.ServerStatus;
import com.l2jmobius.gameserver.network.loginserverpackets.AuthResponse;
import com.l2jmobius.gameserver.network.loginserverpackets.InitLS;
import com.l2jmobius.gameserver.network.loginserverpackets.KickPlayer;
import com.l2jmobius.gameserver.network.loginserverpackets.LoginServerFail;
import com.l2jmobius.gameserver.network.loginserverpackets.PlayerAuthResponse;
import com.l2jmobius.gameserver.network.serverpackets.AuthLoginFail;
import com.l2jmobius.gameserver.network.serverpackets.CharSelectInfo;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.util.Rnd;
import com.l2jmobius.util.Util;
import com.l2jmobius.util.crypt.NewCrypt;
import javolution.util.FastList;
import javolution.util.FastMap;
public class LoginServerThread extends Thread
{
protected static Logger _log = Logger.getLogger(LoginServerThread.class.getName());
/** The LoginServerThread singleton */
private static LoginServerThread _instance;
private static final int REVISION = 0x0102;
private final String _hostname;
private final int _port;
private final int _gamePort;
private Socket _loginSocket;
private OutputStream _out;
/**
* The BlowFish engine used to encrypt packets<br>
* It is first initialized with a unified key:<br>
* "_;v.]05-31!|+-%xT!^[$\00"<br>
* <br>
* and then after handshake, with a new key sent by<br>
* loginserver during the handshake.
*/
private NewCrypt _blowfish;
private byte[] _hexID;
private final boolean _acceptAlternate;
private final int _requestID;
private int _serverID;
private final boolean _reserveHost;
private int _maxPlayer;
private final List<WaitingClient> _waitingClients;
private final Map<String, L2GameClient> _accountsInGameServer;
private int _status;
private String _serverName;
private final String _gameExternalHost;
private final String _gameInternalHost;
public LoginServerThread()
{
super("LoginServerThread");
_port = Config.GAME_SERVER_LOGIN_PORT;
_gamePort = Config.PORT_GAME;
_hostname = Config.GAME_SERVER_LOGIN_HOST;
_hexID = Config.HEX_ID;
if (_hexID == null)
{
_hexID = generateHex(16);
}
_acceptAlternate = Config.ACCEPT_ALTERNATE_ID;
_requestID = Config.REQUEST_ID;
_reserveHost = Config.RESERVE_HOST_ON_LOGIN;
_gameExternalHost = Config.EXTERNAL_HOSTNAME;
_gameInternalHost = Config.INTERNAL_HOSTNAME;
_waitingClients = new FastList<>();
_accountsInGameServer = new FastMap<>();
_maxPlayer = Config.MAXIMUM_ONLINE_USERS;
}
public static LoginServerThread getInstance()
{
if (_instance == null)
{
_instance = new LoginServerThread();
}
return _instance;
}
@Override
public void run()
{
while (!isInterrupted())
{
int lengthHi = 0;
int lengthLo = 0;
int length = 0;
boolean checksumOk = false;
try
{
// Connection
_log.info("Connecting to login on " + _hostname + ":" + _port);
_loginSocket = new Socket(_hostname, _port);
final InputStream in = _loginSocket.getInputStream();
_out = new BufferedOutputStream(_loginSocket.getOutputStream());
// init Blowfish
final byte[] blowfishKey = generateHex(40);
// Protect the new blowfish key what cannot begin with zero
if (blowfishKey[0] == 0)
{
blowfishKey[0] = (byte) Rnd.get(32, 64);
}
_blowfish = new NewCrypt("_;v.]05-31!|+-%xT!^[$\00");
while (!isInterrupted())
{
lengthLo = in.read();
lengthHi = in.read();
length = (lengthHi * 256) + lengthLo;
if (lengthHi < 0)
{
_log.finer("LoginServerThread: Login terminated the connection.");
break;
}
final byte[] incoming = new byte[length - 2];
int receivedBytes = 0;
int newBytes = 0;
int left = length - 2;
while ((newBytes != -1) && (receivedBytes < (length - 2)))
{
newBytes = in.read(incoming, receivedBytes, left);
receivedBytes = receivedBytes + newBytes;
left -= newBytes;
}
if (receivedBytes != (length - 2))
{
_log.warning("Incomplete Packet is sent to the server, closing connection.(LS)");
break;
}
// decrypt if we have a key
_blowfish.decrypt(incoming, 0, incoming.length);
checksumOk = NewCrypt.verifyChecksum(incoming);
if (!checksumOk)
{
_log.warning("Incorrect packet checksum, ignoring packet (LS)");
break;
}
switch (incoming[0] & 0xff)
{
case 0x00:
{
final InitLS init = new InitLS(incoming);
if (init.getRevision() != REVISION)
{
// TODO: revision mismatch
_log.warning("/!\\ Revision mismatch between LS and GS /!\\");
break;
}
RSAPublicKey publicKey;
try
{
publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(new BigInteger(init.getRSAKey()), RSAKeyGenParameterSpec.F4));
}
catch (GeneralSecurityException e)
{
_log.warning("Trouble while init the public key send by login");
break;
}
// send the blowfish key through the rsa encryption
sendPacket(new BlowFishKey(blowfishKey, publicKey));
// now, only accept packet with the new encryption
_blowfish = new NewCrypt(blowfishKey);
final AuthRequest ar = new AuthRequest(_requestID, _acceptAlternate, _hexID, _gameExternalHost, _gameInternalHost, _gamePort, _reserveHost, _maxPlayer);
sendPacket(ar);
break;
}
case 0x01:
{
final LoginServerFail lsf = new LoginServerFail(incoming);
_log.info("Damn! Registration Failed: " + lsf.getReasonString());
// login will close the connection here
break;
}
case 0x02:
{
final AuthResponse aresp = new AuthResponse(incoming);
_serverID = aresp.getServerId();
_serverName = aresp.getServerName();
Config.saveHexid(hexToString(_hexID));
_log.info("Registered on login as Server " + _serverID + " : " + _serverName);
final ServerStatus st = new ServerStatus();
if (Config.SERVER_LIST_BRACKET)
{
st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.ON);
}
else
{
st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.OFF);
}
if (Config.SERVER_LIST_CLOCK)
{
st.addAttribute(ServerStatus.SERVER_LIST_CLOCK, ServerStatus.ON);
}
else
{
st.addAttribute(ServerStatus.SERVER_LIST_CLOCK, ServerStatus.OFF);
}
if (Config.SERVER_LIST_TESTSERVER)
{
st.addAttribute(ServerStatus.TEST_SERVER, ServerStatus.ON);
}
else
{
st.addAttribute(ServerStatus.TEST_SERVER, ServerStatus.OFF);
}
if (Config.SERVER_GMONLY)
{
st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GM_ONLY);
}
else
{
st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_AUTO);
}
sendPacket(st);
if (L2World.getInstance().getAllPlayersCount() > 0)
{
final FastList<String> playerList = new FastList<>();
for (final L2PcInstance player : L2World.getInstance().getAllPlayers())
{
playerList.add(player.getAccountName());
}
final PlayerInGame pig = new PlayerInGame(playerList);
sendPacket(pig);
}
break;
}
case 0x03:
{
final PlayerAuthResponse par = new PlayerAuthResponse(incoming);
final String account = par.getAccount();
WaitingClient wcToRemove = null;
synchronized (_waitingClients)
{
for (WaitingClient wc : _waitingClients)
{
if (wc.account.equals(account))
{
wcToRemove = wc;
}
}
}
if (wcToRemove != null)
{
if (par.isAuthed())
{
final PlayerInGame pig = new PlayerInGame(par.getAccount());
sendPacket(pig);
wcToRemove.gameClient.setState(GameClientState.AUTHED);
wcToRemove.gameClient.setSessionId(wcToRemove.session);
final CharSelectInfo cl = new CharSelectInfo(wcToRemove.account, wcToRemove.gameClient.getSessionId().playOkID1);
wcToRemove.gameClient.getConnection().sendPacket(cl);
wcToRemove.gameClient.setCharSelection(cl.getCharInfo());
}
else
{
_log.warning("session key is not correct. closing connection");
wcToRemove.gameClient.sendPacket(new AuthLoginFail(AuthLoginFail.SYSTEM_ERROR_LOGIN_LATER));
wcToRemove.gameClient.close(new AuthLoginFail(AuthLoginFail.SYSTEM_ERROR_LOGIN_LATER));
_accountsInGameServer.remove(wcToRemove.account);
}
_waitingClients.remove(wcToRemove);
}
break;
}
case 0x04:
{
final KickPlayer kp = new KickPlayer(incoming);
doKickPlayer(kp.getAccount());
break;
}
}
}
}
catch (final UnknownHostException e)
{
if (Config.DEBUG)
{
e.printStackTrace();
}
}
catch (final IOException e)
{
_log.info("Disconnected from Login, Trying to reconnect:");
_log.info(e.toString());
}
finally
{
try
{
_loginSocket.close();
}
catch (final Exception e)
{
}
}
try
{
Thread.sleep(5000); // 5 seconds tempo.
}
catch (final InterruptedException e)
{
return;
}
}
}
public void addWaitingClientAndSendRequest(String acc, L2GameClient client, SessionKey key)
{
if (Config.DEBUG)
{
System.out.println(key);
}
final WaitingClient wc = new WaitingClient(acc, client, key);
synchronized (_waitingClients)
{
_waitingClients.add(wc);
}
final PlayerAuthRequest par = new PlayerAuthRequest(acc, key);
try
{
sendPacket(par);
}
catch (final IOException e)
{
_log.warning("Error while sending player auth request.");
if (Config.DEBUG)
{
e.printStackTrace();
}
}
}
public void removeWaitingClient(L2GameClient client)
{
WaitingClient toRemove = null;
synchronized (_waitingClients)
{
for (final WaitingClient c : _waitingClients)
{
if (c.gameClient == client)
{
toRemove = c;
}
}
if (toRemove != null)
{
_waitingClients.remove(toRemove);
}
}
}
public void sendLogout(String account)
{
final PlayerLogout pl = new PlayerLogout(account);
try
{
sendPacket(pl);
}
catch (final IOException e)
{
_log.warning("Error while sending logout packet to login");
if (Config.DEBUG)
{
e.printStackTrace();
}
}
finally
{
_accountsInGameServer.remove(account);
}
}
public void addGameServerLogin(String account, L2GameClient client)
{
_accountsInGameServer.put(account, client);
}
public boolean getAccountInGameServer(String account)
{
return _accountsInGameServer.get(account) != null;
}
public void sendAccessLevel(String account, int level)
{
final ChangeAccessLevel cal = new ChangeAccessLevel(account, level);
try
{
sendPacket(cal);
}
catch (final IOException e)
{
if (Config.DEBUG)
{
e.printStackTrace();
}
}
}
private String hexToString(byte[] hex)
{
return new BigInteger(hex).toString(16);
}
public void doKickPlayer(String account)
{
final L2GameClient client = _accountsInGameServer.get(account);
if (client != null)
{
client.cancelCleanup(); // delayed cleanup
final L2PcInstance player = client.getActiveChar();
if (player != null)
{
player.sendPacket(new SystemMessage(SystemMessage.ANOTHER_LOGIN_WITH_ACCOUNT));
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (player.isOnline() > 0)
{
player.logout(false);
}
}, 400);
}
else
{
client.closeNow();
}
LoginServerThread.getInstance().sendLogout(account);
}
}
public static byte[] generateHex(int size)
{
final byte[] array = new byte[size];
Rnd.nextBytes(array);
if (Config.DEBUG)
{
_log.fine("Generated random String: \"" + array + "\"");
}
return array;
}
/**
* @param sl
* @throws IOException
*/
private void sendPacket(GameServerBasePacket sl) throws IOException
{
byte[] data = sl.getContent();
NewCrypt.appendChecksum(data);
if (Config.DEBUG)
{
_log.finest("[S]\n" + Util.printData(data));
}
_blowfish.crypt(data, 0, data.length);
final int len = data.length + 2;
synchronized (_out) // avoids two threads writing in the mean time
{
_out.write(len & 0xff);
_out.write((len >> 8) & 0xff);
_out.write(data);
_out.flush();
}
}
/**
* Sets the max player.
* @param maxPlayer The maxPlayer to set.
*/
public void setMaxPlayer(int maxPlayer)
{
sendServerStatus(ServerStatus.MAX_PLAYERS, maxPlayer);
_maxPlayer = maxPlayer;
}
/**
* Gets the max player.
* @return Returns the maxPlayer.
*/
public int getMaxPlayer()
{
return _maxPlayer;
}
/**
* Send server status.
* @param id the id
* @param value the value
*/
public void sendServerStatus(int id, int value)
{
final ServerStatus ss = new ServerStatus();
ss.addAttribute(id, value);
try
{
sendPacket(ss);
}
catch (final IOException e)
{
if (Config.DEBUG)
{
e.printStackTrace();
}
}
}
/**
* @return
*/
public String getStatusString()
{
return ServerStatus.statusString[_status];
}
/**
* @return
*/
public boolean isClockShown()
{
return Config.SERVER_LIST_CLOCK;
}
/**
* @return
*/
public boolean isBracketShown()
{
return Config.SERVER_LIST_BRACKET;
}
/**
* Gets the server name.
* @return the server name.
*/
public String getServerName()
{
return _serverName;
}
/**
* Sets the server status.
* @param status the new server status
*/
public void setServerStatus(int status)
{
switch (status)
{
case ServerStatus.STATUS_AUTO:
{
sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_AUTO);
_status = status;
break;
}
case ServerStatus.STATUS_DOWN:
{
sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_DOWN);
_status = status;
break;
}
case ServerStatus.STATUS_FULL:
{
sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_FULL);
_status = status;
break;
}
case ServerStatus.STATUS_GM_ONLY:
{
sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GM_ONLY);
_status = status;
break;
}
case ServerStatus.STATUS_GOOD:
{
sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GOOD);
_status = status;
break;
}
case ServerStatus.STATUS_NORMAL:
{
sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_NORMAL);
_status = status;
break;
}
default:
{
throw new IllegalArgumentException("Status does not exists:" + status);
}
}
}
public static class SessionKey
{
public int playOkID1;
public int playOkID2;
public int loginOkID1;
public int loginOkID2;
/**
* Instantiates a new session key.
* @param loginOK1 the login o k1
* @param loginOK2 the login o k2
* @param playOK1 the play o k1
* @param playOK2 the play o k2
*/
public SessionKey(int loginOK1, int loginOK2, int playOK1, int playOK2)
{
playOkID1 = playOK1;
playOkID2 = playOK2;
loginOkID1 = loginOK1;
loginOkID2 = loginOK2;
}
@Override
public String toString()
{
return "PlayOk: " + playOkID1 + " " + playOkID2 + " LoginOk:" + loginOkID1 + " " + loginOkID2;
}
}
private static class WaitingClient
{
public String account;
public L2GameClient gameClient;
public SessionKey session;
/**
* Instantiates a new waiting client.
* @param acc the acc
* @param client the client
* @param key the key
*/
public WaitingClient(String acc, L2GameClient client, SessionKey key)
{
account = acc;
gameClient = client;
session = key;
}
}
}

View File

@@ -0,0 +1,152 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.lang.reflect.Constructor;
import com.l2jmobius.gameserver.datatables.NpcTable;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jmobius.gameserver.templates.L2NpcTemplate;
import com.l2jmobius.util.Rnd;
@SuppressWarnings("rawtypes")
public class MonsterRace
{
private final L2NpcInstance[] monsters;
private static MonsterRace _instance;
private Constructor _constructor;
private int[][] speeds;
private final int[] first, second;
private MonsterRace()
{
monsters = new L2NpcInstance[8];
speeds = new int[8][20];
first = new int[2];
second = new int[2];
}
public static MonsterRace getInstance()
{
if (_instance == null)
{
_instance = new MonsterRace();
}
return _instance;
}
public void newRace()
{
int random = 0;
for (int i = 0; i < 8; i++)
{
final int id = 8003;
random = Rnd.get(24);
while (true)
{
for (int j = i - 1; j >= 0; j--)
{
if (monsters[j].getTemplate().npcId == (id + random))
{
random = Rnd.get(24);
continue;
}
}
break;
}
try
{
final L2NpcTemplate template = NpcTable.getInstance().getTemplate(id + random);
_constructor = Class.forName("com.l2jmobius.gameserver.model.actor.instance." + template.type + "Instance").getConstructors()[0];
final int objectId = IdFactory.getInstance().getNextId();
monsters[i] = (L2NpcInstance) _constructor.newInstance(objectId, template);
}
catch (final Exception e)
{
e.printStackTrace();
}
}
newSpeeds();
}
public void newSpeeds()
{
speeds = new int[8][20];
int total = 0;
first[1] = 0;
second[1] = 0;
for (int i = 0; i < 8; i++)
{
total = 0;
for (int j = 0; j < 20; j++)
{
if (j == 19)
{
speeds[i][j] = 100;
}
else
{
speeds[i][j] = Rnd.get(60) + 65;
}
total += speeds[i][j];
}
if (total >= first[1])
{
second[0] = first[0];
second[1] = first[1];
first[0] = 8 - i;
first[1] = total;
}
else if (total >= second[1])
{
second[0] = 8 - i;
second[1] = total;
}
}
}
/**
* @return Returns the monsters.
*/
public L2NpcInstance[] getMonsters()
{
return monsters;
}
/**
* @return Returns the speeds.
*/
public int[][] getSpeeds()
{
return speeds;
}
public int getFirstPlace()
{
return first[0];
}
public int getSecondPlace()
{
return second[0];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,869 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.LineNumberReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.WeakHashMap;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.Inventory;
import com.l2jmobius.gameserver.model.L2ItemInstance;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2RecipeInstance;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import com.l2jmobius.gameserver.network.serverpackets.ItemList;
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jmobius.gameserver.network.serverpackets.RecipeBookItemList;
import com.l2jmobius.gameserver.network.serverpackets.RecipeItemMakeInfo;
import com.l2jmobius.gameserver.network.serverpackets.RecipeShopItemInfo;
import com.l2jmobius.gameserver.network.serverpackets.SetupGauge;
import com.l2jmobius.gameserver.network.serverpackets.StatusUpdate;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.skills.Stats;
import com.l2jmobius.gameserver.util.Util;
import com.l2jmobius.util.Rnd;
import javolution.util.FastList;
import javolution.util.FastMap;
public class RecipeController
{
protected static Logger _log = Logger.getLogger(RecipeController.class.getName());
private static RecipeController _instance;
private final Map<Integer, L2RecipeList> _lists;
protected static Map<L2PcInstance, RecipeItemMaker> activeMakers = Collections.synchronizedMap(new WeakHashMap<L2PcInstance, RecipeItemMaker>());
public static RecipeController getInstance()
{
return _instance == null ? _instance = new RecipeController() : _instance;
}
public RecipeController()
{
_lists = new FastMap<>();
String line = null;
final File recipesData = new File(Config.DATAPACK_ROOT, "data/recipes.csv");
try (FileReader fr = new FileReader(recipesData);
BufferedReader br = new BufferedReader(fr);
LineNumberReader lnr = new LineNumberReader(br))
{
while ((line = lnr.readLine()) != null)
{
if ((line.trim().length() == 0) || line.startsWith("#"))
{
continue;
}
parseList(line);
}
_log.config("RecipeController: Loaded " + _lists.size() + " Recipes.");
}
catch (final Exception e)
{
_log.warning("Error loading recipes.");
}
}
public int getRecipesCount()
{
return _lists.size();
}
public L2RecipeList getRecipeList(int listId)
{
return _lists.get(listId);
}
public L2RecipeList getRecipeByItemId(int itemId)
{
for (int i = 0; i < _lists.size(); i++)
{
final L2RecipeList find = _lists.get(new Integer(i));
if (find.getRecipeId() == itemId)
{
return find;
}
}
return null;
}
public L2RecipeList getRecipeById(int recId)
{
for (int i = 0; i < _lists.size(); i++)
{
final L2RecipeList find = _lists.get(new Integer(i));
if (find.getId() == recId)
{
return find;
}
}
return null;
}
public synchronized void requestBookOpen(L2PcInstance player, boolean isDwarvenCraft)
{
RecipeItemMaker maker = null;
if (Config.ALT_GAME_CREATION)
{
maker = activeMakers.get(player);
}
if (maker == null)
{
final RecipeBookItemList response = new RecipeBookItemList(isDwarvenCraft, player.getMaxMp());
response.addRecipes(isDwarvenCraft ? player.getDwarvenRecipeBook() : player.getCommonRecipeBook());
player.sendPacket(response);
return;
}
final SystemMessage sm = new SystemMessage(SystemMessage.CANT_ALTER_RECIPEBOOK_WHILE_CRAFTING);
player.sendPacket(sm);
return;
}
public synchronized void requestMakeItemAbort(L2PcInstance player)
{
activeMakers.remove(player); // TODO: anything else here?
}
public synchronized void requestManufactureItem(L2PcInstance manufacturer, int recipeListId, L2PcInstance player)
{
final L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
if (recipeList == null)
{
return;
}
final List<L2RecipeList> dwarfRecipes = Arrays.asList(manufacturer.getDwarvenRecipeBook());
final List<L2RecipeList> commonRecipes = Arrays.asList(manufacturer.getCommonRecipeBook());
if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList))
{
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
return;
}
RecipeItemMaker maker;
if (Config.ALT_GAME_CREATION && ((maker = activeMakers.get(manufacturer)) != null)) // check if busy
{
player.sendMessage("Manufacturer is busy, please try later.");
return;
}
maker = new RecipeItemMaker(manufacturer, recipeList, player);
if (maker.isValid)
{
if (Config.ALT_GAME_CREATION)
{
activeMakers.put(manufacturer, maker);
ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
}
else
{
maker.run();
}
}
}
public synchronized void requestMakeItem(L2PcInstance player, int recipeListId)
{
final L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
if (recipeList == null)
{
return;
}
final List<L2RecipeList> dwarfRecipes = Arrays.asList(player.getDwarvenRecipeBook());
final List<L2RecipeList> commonRecipes = Arrays.asList(player.getCommonRecipeBook());
if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList))
{
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
return;
}
RecipeItemMaker maker;
// check if already busy (possible in alt mode only)
if (Config.ALT_GAME_CREATION && ((maker = activeMakers.get(player)) != null))
{
final SystemMessage sm = new SystemMessage(614);
sm.addString("You are busy creating ");
sm.addItemName(recipeList.getItemId());
player.sendPacket(sm);
return;
}
maker = new RecipeItemMaker(player, recipeList, player);
if (maker.isValid)
{
if (Config.ALT_GAME_CREATION)
{
activeMakers.put(player, maker);
ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
}
else
{
maker.run();
}
}
}
private void parseList(String line)
{
try
{
final StringTokenizer st = new StringTokenizer(line, ";");
final List<L2RecipeInstance> recipePartList = new FastList<>();
// we use common/dwarf for easy reading of the recipes.csv file
final String recipeTypeString = st.nextToken();
// now parse the string into a boolean
boolean isDwarvenRecipe;
if (recipeTypeString.equalsIgnoreCase("dwarven"))
{
isDwarvenRecipe = true;
}
else if (recipeTypeString.equalsIgnoreCase("common"))
{
isDwarvenRecipe = false;
}
else
{ // prints a helpfull message
_log.warning("Error parsing recipes.csv, unknown recipe type " + recipeTypeString);
return;
}
final String recipeName = st.nextToken();
final int id = Integer.parseInt(st.nextToken());
final int recipeId = Integer.parseInt(st.nextToken());
final int level = Integer.parseInt(st.nextToken());
// material
final StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");
while (st2.hasMoreTokens())
{
final StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
final int rpItemId = Integer.parseInt(st3.nextToken());
final int quantity = Integer.parseInt(st3.nextToken());
final L2RecipeInstance rp = new L2RecipeInstance(rpItemId, quantity);
recipePartList.add(rp);
}
final int itemId = Integer.parseInt(st.nextToken());
final int count = Integer.parseInt(st.nextToken());
// npc fee
/* String notdoneyet = */st.nextToken();
final int mpCost = Integer.parseInt(st.nextToken());
final int successRate = Integer.parseInt(st.nextToken());
final L2RecipeList recipeList = new L2RecipeList(id, level, recipeId, recipeName, successRate, mpCost, itemId, count, isDwarvenRecipe);
for (final L2RecipeInstance recipePart : recipePartList)
{
recipeList.addRecipe(recipePart);
}
_lists.put(new Integer(_lists.size()), recipeList);
}
catch (final Exception e)
{
_log.severe("Exception in RecipeController.parseList() - " + e);
}
}
public class RecipeItemMaker implements Runnable
{
public boolean isValid;
List<TempItem> items = null;
final L2RecipeList recipeList;
final L2PcInstance player; // "crafter"
final L2PcInstance target; // "customer"
final L2Skill skill;
final int skillId;
final int skillLevel;
double creationPasses;
double manaRequired;
int price;
int totalItems;
int materialsRefPrice;
int delay;
public RecipeItemMaker(L2PcInstance pPlayer, L2RecipeList pRecipeList, L2PcInstance pTarget)
{
player = pPlayer;
target = pTarget;
recipeList = pRecipeList;
isValid = false;
skillId = recipeList.isDwarvenRecipe() ? L2Skill.SKILL_CREATE_DWARVEN : L2Skill.SKILL_CREATE_COMMON;
skillLevel = player.getSkillLevel(skillId);
skill = player.getKnownSkill(skillId);
player.isInCraftMode(true);
if (player.isAlikeDead())
{
player.sendMessage("Dead people can't craft.");
player.sendPacket(new ActionFailed());
abort();
return;
}
if (target.isAlikeDead())
{
target.sendMessage("Dead customers can't use manufacture.");
target.sendPacket(new ActionFailed());
abort();
return;
}
if (target.isProcessingTransaction())
{
target.sendMessage("You are busy.");
target.sendPacket(new ActionFailed());
abort();
return;
}
if (player.isProcessingTransaction())
{
if (player != target)
{
target.sendMessage("Manufacturer " + player.getName() + " is busy.");
}
player.sendPacket(new ActionFailed());
abort();
return;
}
// validate recipe list
if ((recipeList == null) || (recipeList.getRecipes().length == 0))
{
player.sendMessage("No such recipe.");
player.sendPacket(new ActionFailed());
abort();
return;
}
manaRequired = recipeList.getMpCost();
// validate skill level
if (recipeList.getLevel() > skillLevel)
{
player.sendMessage("Need skill level " + recipeList.getLevel());
player.sendPacket(new ActionFailed());
abort();
return;
}
// check that customer can afford to pay for creation services
if (player != target)
{
for (final L2ManufactureItem temp : player.getCreateList().getList())
{
if (temp.getRecipeId() == recipeList.getId()) // find recipe for item we want manufactured
{
price = temp.getCost();
if (target.getAdena() < price) // check price
{
target.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));
abort();
return;
}
break;
}
}
}
// make temporary items
if ((items = listItems(false)) == null)
{
abort();
return;
}
// calculate reference price
for (final TempItem i : items)
{
materialsRefPrice += i.getReferencePrice() * i.getQuantity();
totalItems += i.getQuantity();
}
// initial mana check requires MP as written on recipe
if (player.getCurrentMp() < manaRequired)
{
target.sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP));
abort();
return;
}
// determine number of creation passes needed
// can "equip" skillLevel items each pass
creationPasses = (totalItems / skillLevel) + ((totalItems % skillLevel) != 0 ? 1 : 0);
if (Config.ALT_GAME_CREATION && (creationPasses != 0))
{
manaRequired /= creationPasses; // checks to validateMp() will only need portion of mp for one pass
}
updateMakeInfo(true);
updateCurMp();
updateCurLoad();
player.isInCraftMode(false);
isValid = true;
}
@Override
public void run()
{
if (!Config.IS_CRAFTING_ENABLED)
{
target.sendMessage("Item creation is currently disabled.");
abort();
return;
}
if ((player == null) || (target == null))
{
_log.warning("player or target == null (disconnected?), aborting" + target + player);
abort();
return;
}
if ((player.isOnline() == 0) || (target.isOnline() == 0))
{
_log.warning("player or target is not online, aborting " + target + player);
abort();
return;
}
if (Config.ALT_GAME_CREATION && (activeMakers.get(player) == null))
{
if (target != player)
{
target.sendMessage("Manufacture aborted");
player.sendMessage("Manufacture aborted");
}
else
{
player.sendMessage("Item creation aborted");
}
abort();
return;
}
if (Config.ALT_GAME_CREATION && !items.isEmpty())
{
if (!validateMp())
{
return; // check mana
}
player.reduceCurrentMp(manaRequired); // use some mp
updateCurMp(); // update craft window mp bar
grabSomeItems(); // grab (equip) some more items with a nice msg to player
// if still not empty, schedule another pass
if (!items.isEmpty())
{
// divided by RATE_CONSUMABLES_COST to remove craft time increase on higher consumables rates
delay = (int) ((Config.ALT_GAME_CREATION_SPEED * player.getMReuseRate(skill) * GameTimeController.TICKS_PER_SECOND) / Config.RATE_CONSUMABLE_COST) * GameTimeController.MILLIS_IN_TICK;
// FIXME: please fix this packet to show crafting animation (somebody)
final MagicSkillUse msk = new MagicSkillUse(player, skillId, skillLevel, delay, 0);
player.broadcastPacket(msk);
player.sendPacket(new SetupGauge(0, delay));
ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + delay);
}
else
{
// for alt mode, sleep delay msec before finishing
player.sendPacket(new SetupGauge(0, delay));
try
{
Thread.sleep(delay);
}
catch (final InterruptedException e)
{
}
finally
{
finishCrafting();
}
}
} // for old craft mode just finish
else
{
finishCrafting();
}
}
private void finishCrafting()
{
if (!Config.ALT_GAME_CREATION)
{
player.reduceCurrentMp(manaRequired);
}
// first take adena for manufacture
if ((target != player) && (price > 0)) // customer must pay for services
{
// attempt to pay for item
final L2ItemInstance adenatransfer = target.transferItem("PayManufacture", target.getInventory().getAdenaInstance().getObjectId(), price, player.getInventory(), player);
if (adenatransfer == null)
{
target.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));
abort();
return;
}
}
if ((items = listItems(true)) == null) // this line actually takes materials from inventory
{ // handle possible cheaters here
// (they click craft then try to get rid of items in order to get free craft)
}
else if (Rnd.get(100) < recipeList.getSuccessRate())
{
RewardPlayer(); // and immediately puts created item in its place
updateMakeInfo(true);
}
else
{
player.sendMessage("Item(s) failed to create.");
if (target != player)
{
target.sendMessage("Item(s) failed to create.");
}
updateMakeInfo(false);
}
// update load and mana bar of craft window
updateCurMp();
updateCurLoad();
activeMakers.remove(player);
player.isInCraftMode(false);
target.sendPacket(new ItemList(target, false));
}
private void updateMakeInfo(boolean success)
{
if (target == player)
{
target.sendPacket(new RecipeItemMakeInfo(recipeList.getId(), target, success));
}
else
{
target.sendPacket(new RecipeShopItemInfo(player.getObjectId(), recipeList.getId()));
}
}
private void updateCurLoad()
{
final StatusUpdate su = new StatusUpdate(target.getObjectId());
su.addAttribute(StatusUpdate.CUR_LOAD, target.getCurrentLoad());
target.sendPacket(su);
}
private void updateCurMp()
{
final StatusUpdate su = new StatusUpdate(target.getObjectId());
su.addAttribute(StatusUpdate.CUR_MP, (int) target.getCurrentMp());
target.sendPacket(su);
}
private void grabSomeItems()
{
int numItems = skillLevel;
while ((numItems > 0) && !items.isEmpty())
{
final TempItem item = items.get(0);
int count = item.getQuantity();
if (count >= numItems)
{
count = numItems;
}
item.setQuantity(item.getQuantity() - count);
if (item.getQuantity() <= 0)
{
items.remove(0);
}
else
{
items.set(0, item);
}
numItems -= count;
if (target == player)
{
final SystemMessage sm = new SystemMessage(368); // you equipped ...
sm.addNumber(count);
sm.addItemName(item.getItemId());
player.sendPacket(sm);
}
else
{
target.sendMessage("Manufacturer " + player.getName() + " used " + count + " " + item.getItemName());
}
}
}
private boolean validateMp()
{
if (player.getCurrentMp() < manaRequired)
{
// rest (wait for MP)
if (Config.ALT_GAME_CREATION)
{
player.sendPacket(new SetupGauge(0, delay));
ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + delay);
}
else
// no rest - report no mana
{
target.sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP));
abort();
}
return false;
}
return true;
}
private List<TempItem> listItems(boolean remove)
{
final L2RecipeInstance[] recipes = recipeList.getRecipes();
final Inventory inv = target.getInventory();
final List<TempItem> materials = new FastList<>();
for (final L2RecipeInstance recipe : recipes)
{
final int quantity = recipeList.isConsumable() ? (int) (recipe.getQuantity() * Config.RATE_CONSUMABLE_COST) : recipe.getQuantity();
if (quantity > 0)
{
final L2ItemInstance item = inv.getItemByItemId(recipe.getItemId());
// check materials
if ((item == null) || (item.getCount() < quantity))
{
target.sendMessage("You dont have the right elements for making this item" + ((recipeList.isConsumable() && (Config.RATE_CONSUMABLE_COST != 1)) ? ".\nDue to server rates you need " + Config.RATE_CONSUMABLE_COST + "x more material than listed in recipe" : ""));
abort();
return null;
}
// make new temporary object, just for counting puroses
final TempItem temp = new TempItem(item, quantity);
materials.add(temp);
}
}
if (remove)
{
for (final TempItem tmp : materials)
{
inv.destroyItemByItemId("Manufacture", tmp.getItemId(), tmp.getQuantity(), target, player);
}
}
return materials;
}
private void abort()
{
updateMakeInfo(false);
player.isInCraftMode(false);
activeMakers.remove(player);
}
/**
* FIXME: This class should be in some other file, but I don't know where Class explanation: For item counting or checking purposes. When you don't want to modify inventory class contains itemId, quantity, ownerId, referencePrice, but not objectId
*/
private class TempItem
{
// no object id stored, this will be only "list" of items with it's owner
private final int _itemId;
private int _quantity;
// private final int _ownerId;
private final int _referencePrice;
private final String _itemName;
/**
* @param item
* @param quantity of that item
*/
public TempItem(L2ItemInstance item, int quantity)
{
super();
_itemId = item.getItemId();
_quantity = quantity;
// _ownerId = item.getOwnerId();
_itemName = item.getItem().getName();
_referencePrice = item.getReferencePrice();
}
/**
* @return Returns the quantity.
*/
public int getQuantity()
{
return _quantity;
}
/**
* @param quantity The quantity to set.
*/
public void setQuantity(int quantity)
{
_quantity = quantity;
}
public int getReferencePrice()
{
return _referencePrice;
}
/**
* @return Returns the itemId.
*/
public int getItemId()
{
return _itemId;
}
/**
* @return Returns the ownerId.
*/
// public int getOwnerId()
// {
// return _ownerId;
// }
/**
* @return Returns the itemName.
*/
public String getItemName()
{
return _itemName;
}
}
private void RewardPlayer()
{
final int itemId = recipeList.getItemId();
final int itemCount = recipeList.getCount();
final L2ItemInstance createdItem = target.getInventory().addItem("Manufacture", itemId, itemCount, target, player);
// inform customer of earned item
SystemMessage sm = null;
if (itemCount > 1)
{
sm = new SystemMessage(SystemMessage.EARNED_S2_S1_s);
sm.addItemName(itemId);
sm.addNumber(itemCount);
target.sendPacket(sm);
}
else
{
sm = new SystemMessage(SystemMessage.EARNED_ITEM);
sm.addItemName(itemId);
target.sendPacket(sm);
}
if (target != player)
{
// inform manufacturer of earned profit
sm = new SystemMessage(SystemMessage.EARNED_ADENA);
sm.addNumber(price);
player.sendPacket(sm);
}
if (Config.ALT_GAME_CREATION)
{
final int recipeLevel = recipeList.getLevel();
long exp = createdItem.getReferencePrice() * itemCount;
// one variation
// exp -= materialsRefPrice; // mat. ref. price is not accurate so other method is better
if (exp < 0)
{
exp = 0;
}
// another variation
exp /= recipeLevel;
for (int i = skillLevel; i > recipeLevel; i--)
{
exp /= 4;
}
final long sp = exp / 10;
// Added multiplication of Creation speed with XP/SP gain
// slower crafting -> more XP, faster crafting -> less XP
// you can use ALT_GAME_CREATION_XP_RATE/SP to
// modify XP/SP gained (default = 1)
player.addExpAndSp((long) player.calcStat(Stats.EXPSP_RATE, exp * Config.ALT_GAME_CREATION_XP_RATE * Config.ALT_GAME_CREATION_SPEED, null, null), (int) player.calcStat(Stats.EXPSP_RATE, sp * Config.ALT_GAME_CREATION_SP_RATE * Config.ALT_GAME_CREATION_SPEED, null, null));
}
updateMakeInfo(true); // success
}
}
private L2RecipeList getValidRecipeList(L2PcInstance player, int id)
{
final L2RecipeList recipeList = getRecipeList(id - 1);
if ((recipeList == null) || (recipeList.getRecipes().length == 0))
{
player.sendMessage("No recipe for: " + id);
player.isInCraftMode(false);
return null;
}
return recipeList;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,509 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.datatables.OfflineTradersTable;
import com.l2jmobius.gameserver.instancemanager.CastleManorManager;
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
import com.l2jmobius.gameserver.instancemanager.QuestManager;
import com.l2jmobius.gameserver.instancemanager.RaidBossSpawnManager;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.gameserverpackets.ServerStatus;
/**
* This class provides the functions for shutting down and restarting the server It closes all open clientconnections and saves all data.
* @version $Revision: 1.2.4.5 $ $Date: 2005/03/27 15:29:09 $
*/
public class Shutdown extends Thread
{
private static Logger _log = Logger.getLogger(Shutdown.class.getName());
private static Shutdown _instance;
private static Shutdown _counterInstance = null;
private int secondsShut;
private int shutdownMode;
public static final int SIGTERM = 0;
public static final int GM_SHUTDOWN = 1;
public static final int GM_RESTART = 2;
public static final int ABORT = 3;
private static String[] _modeText =
{
"SIGTERM",
"shutting down",
"restarting",
"aborting"
};
/**
* This function starts a shutdown countdown from Telnet (Copied from Function startShutdown())
* @param IP Which Issued shutdown command
* @param seconds seconds untill shutdown
* @param restart true if the server will restart after shutdown
*/
public void startTelnetShutdown(String IP, int seconds, boolean restart)
{
final Announcements _an = Announcements.getInstance();
_log.warning("IP: " + IP + " issued shutdown command. " + _modeText[shutdownMode] + " in " + seconds + " seconds!");
if (restart)
{
shutdownMode = GM_RESTART;
}
else
{
shutdownMode = GM_SHUTDOWN;
}
if (shutdownMode > 0)
{
_an.announceToAll("Attention players!");
_an.announceToAll("Server is " + _modeText[shutdownMode] + " in " + seconds + " seconds!");
if ((shutdownMode == 1) || (shutdownMode == 2))
{
_an.announceToAll("Please, avoid to use Gatekeepers/SoE");
_an.announceToAll("during server " + _modeText[shutdownMode] + " procedure.");
}
}
if (_counterInstance != null)
{
_counterInstance._abort();
}
_counterInstance = new Shutdown(seconds, restart);
_counterInstance.start();
}
/**
* This function aborts a running countdown
* @param IP IP Which Issued shutdown command
*/
public void Telnetabort(String IP)
{
_log.warning("IP: " + IP + " issued shutdown ABORT. " + _modeText[shutdownMode] + " has been stopped!");
if (_counterInstance != null)
{
_counterInstance._abort();
final Announcements _an = Announcements.getInstance();
_an.announceToAll("Server aborts " + _modeText[shutdownMode] + " and continues normal operation!");
}
}
/**
* Default constucter is only used internal to create the shutdown-hook instance
*/
public Shutdown()
{
secondsShut = -1;
shutdownMode = SIGTERM;
}
/**
* This creates a countdown instance of Shutdown.
* @param seconds how many seconds until shutdown
* @param restart true is the server shall restart after shutdown
*/
public Shutdown(int seconds, boolean restart)
{
if (seconds < 0)
{
seconds = 0;
}
secondsShut = seconds;
if (restart)
{
shutdownMode = GM_RESTART;
}
else
{
shutdownMode = GM_SHUTDOWN;
}
}
/**
* get the shutdown-hook instance the shutdown-hook instance is created by the first call of this function, but it has to be registrered externaly.
* @return instance of Shutdown, to be used as shutdown hook
*/
public static Shutdown getInstance()
{
if (_instance == null)
{
_instance = new Shutdown();
}
return _instance;
}
/**
* this function is called, when a new thread starts if this thread is the thread of getInstance, then this is the shutdown hook and we save all data and disconnect all clients. after this thread ends, the server will completely exit if this is not the thread of getInstance, then this is a
* countdown thread. we start the countdown, and when we finished it, and it was not aborted, we tell the shutdown-hook why we call exit, and then call exit when the exit status of the server is 1, startServer.sh / startServer.bat will restart the server.
*/
@Override
public void run()
{
// disallow new logins
if (this == _instance)
{
try
{
if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS)
{
OfflineTradersTable.storeOffliners();
}
}
catch (final Throwable t)
{
}
try
{
disconnectAllCharacters();
_log.info("All players have been disconnected.");
}
catch (final Throwable t)
{
}
// ensure all services are stopped
try
{
GameTimeController.getInstance().stopTimer();
}
catch (final Throwable t)
{
}
// stop all threadpools
try
{
ThreadPoolManager.getInstance().shutdown();
}
catch (final Throwable t)
{
}
try
{
LoginServerThread.getInstance().interrupt();
}
catch (final Throwable t)
{
}
// last bye bye, save all data and quit this server
saveData();
// saveData sends messages to exit players, so shutdown selector after it
try
{
GameServer.gameServer.getSelectorThread().shutdown();
}
catch (final Throwable t)
{
}
// commit data, last chance
try
{
L2DatabaseFactory.getInstance().shutdown();
}
catch (final Throwable t)
{
}
// server will quit, when this function ends.
if (_instance.shutdownMode == GM_RESTART)
{
Runtime.getRuntime().halt(2);
}
else
{
Runtime.getRuntime().halt(0);
}
}
else
{
// gm shutdown: send warnings and then call exit to start shutdown sequence
countdown();
// last point where logging is operational :(
_log.warning("GM shutdown countdown is over. " + _modeText[shutdownMode] + " NOW!");
switch (shutdownMode)
{
case GM_SHUTDOWN:
_instance.setMode(GM_SHUTDOWN);
System.exit(0);
break;
case GM_RESTART:
_instance.setMode(GM_RESTART);
System.exit(2);
break;
}
}
}
/**
* This functions starts a shutdown countdown
* @param activeChar GM who issued the shutdown command
* @param seconds seconds until shutdown
* @param restart true if the server will restart after shutdown
*/
public void startShutdown(L2PcInstance activeChar, int seconds, boolean restart)
{
final Announcements _an = Announcements.getInstance();
_log.warning("GM: " + activeChar.getName() + "(" + activeChar.getObjectId() + ") issued shutdown command. " + _modeText[shutdownMode] + " in " + seconds + " seconds!");
if (restart)
{
shutdownMode = GM_RESTART;
}
else
{
shutdownMode = GM_SHUTDOWN;
}
if (shutdownMode > 0)
{
_an.announceToAll("Attention players!");
_an.announceToAll("Server is " + _modeText[shutdownMode] + " in " + seconds + " seconds!");
if ((shutdownMode == 1) || (shutdownMode == 2))
{
_an.announceToAll("Please, avoid to use Gatekeepers/SoE");
_an.announceToAll("during server " + _modeText[shutdownMode] + " procedure.");
}
}
if (_counterInstance != null)
{
_counterInstance._abort();
}
// the main instance should only run for shutdown hook, so we start a new instance
_counterInstance = new Shutdown(seconds, restart);
_counterInstance.start();
}
/**
* This function aborts a running countdown
* @param activeChar GM who issued the abort command
*/
public void abort(L2PcInstance activeChar)
{
_log.warning("GM: " + activeChar.getName() + "(" + activeChar.getObjectId() + ") issued shutdown ABORT. " + _modeText[shutdownMode] + " has been stopped!");
if (_counterInstance != null)
{
_counterInstance._abort();
final Announcements _an = Announcements.getInstance();
_an.announceToAll("Server aborts " + _modeText[shutdownMode] + " and continues normal operation!");
}
}
/**
* set the shutdown mode
* @param mode what mode shall be set
*/
private void setMode(int mode)
{
shutdownMode = mode;
}
/**
* set shutdown mode to ABORT
*/
private void _abort()
{
shutdownMode = ABORT;
}
/**
* this counts the countdown and reports it to all players countdown is aborted if mode changes to ABORT
*/
private void countdown()
{
final Announcements _an = Announcements.getInstance();
try
{
while (secondsShut > 0)
{
switch (secondsShut)
{
case 540:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 9 minutes.");
break;
case 480:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 8 minutes.");
break;
case 420:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 7 minutes.");
break;
case 360:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 6 minutes.");
break;
case 300:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 5 minutes.");
break;
case 240:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 4 minutes.");
break;
case 180:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 3 minutes.");
break;
case 120:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 2 minutes.");
break;
case 60:
LoginServerThread.getInstance().setServerStatus(ServerStatus.STATUS_DOWN); // prevents new players from logging in
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 1 minute.");
break;
case 30:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 30 seconds.");
break;
case 5:
_an.announceToAll("The server is " + _modeText[shutdownMode] + " in 5 seconds, please log out NOW !");
break;
}
secondsShut--;
final int delay = 1000; // milliseconds
Thread.sleep(delay);
if (shutdownMode == ABORT)
{
break;
}
}
}
catch (final InterruptedException e)
{
// this will never happen
}
}
/**
* this sends a last byebye, disconnects all players and saves data
*/
private void saveData()
{
final Announcements _an = Announcements.getInstance();
switch (shutdownMode)
{
case SIGTERM:
_log.info("SIGTERM received. Shutting down NOW!");
break;
case GM_SHUTDOWN:
_log.info("GM shutdown received. Shutting down NOW!");
break;
case GM_RESTART:
_log.info("GM restart received. Restarting NOW!");
break;
}
try
{
_an.announceToAll("Server is " + _modeText[shutdownMode] + " NOW!");
}
catch (final Throwable t)
{
_log.log(Level.INFO, "", t);
}
// Seven Signs data is now saved along with Festival data.
if (!SevenSigns.getInstance().isSealValidationPeriod())
{
SevenSignsFestival.getInstance().saveFestivalData(false);
}
// Save Seven Signs data before closing. :)
SevenSigns.getInstance().saveSevenSignsData(null, true);
// Save all raidboss and grandboss status ^_^
RaidBossSpawnManager.getInstance().cleanUp();
_log.info("RaidBossSpawnManager: All Raid Boss info saved!!");
GrandBossManager.getInstance().cleanUp();
_log.info("GrandBossManager: All Grand Boss info saved!!");
TradeController.getInstance().dataCountStore();
_log.info("TradeController: All count Item Saved!!");
try
{
Olympiad.getInstance().save();
_log.info("Olympiad System: Data saved!!");
}
catch (final Exception e)
{
e.printStackTrace();
}
// Save all manor data
CastleManorManager.getInstance().save();
// Save all global (non-player specific) Quest data that needs to persist after reboot
QuestManager.getInstance().save();
// Save items on ground before closing
if (Config.SAVE_DROPPED_ITEM)
{
ItemsOnGroundManager.getInstance().saveInDb();
ItemsOnGroundManager.getInstance().cleanUp();
_log.info("ItemsOnGroundManager: All items on ground saved!");
}
try
{
final int delay = 5000;
Thread.sleep(delay);
}
catch (final InterruptedException e)
{
// never happens :p
}
}
/**
* this disconnects all clients from the server
*/
private void disconnectAllCharacters()
{
for (final L2PcInstance player : L2World.getInstance().getAllPlayers())
{
// Logout Character
try
{
player.logout(false);
}
catch (final Throwable t)
{
}
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.model.L2Territory;
import com.l2jmobius.util.SqlUtils;
import javolution.util.FastMap;
/**
* coded by Balancer ported to L2JRU by Mr balancer@balancer.ru http://balancer.ru version 0.1.1, 2005-06-07 version 0.1, 2005-03-16
*/
public class Territory
{
private static Logger _log = Logger.getLogger(TradeController.class.getName());
private static final Territory _instance = new Territory();
private static Map<Integer, L2Territory> _territory;
public static Territory getInstance()
{
return _instance;
}
private Territory()
{
// load all data at server start
reload_data();
}
public int[] getRandomPoint(int terr)
{
return _territory.get(terr).getRandomPoint();
}
public int getProcMax(int terr)
{
return _territory.get(terr).getProcMax();
}
public void reload_data()
{
_territory = new FastMap<>();
final Integer[][] point = SqlUtils.get2DIntArray(new String[]
{
"loc_id",
"loc_x",
"loc_y",
"loc_zmin",
"loc_zmax",
"proc"
}, "locations", "loc_id > 0");
for (final Integer[] row : point)
{
// _log.info("row = "+row[0]);
final Integer terr = row[0];
if (terr == null)
{
_log.warning("Null territory!");
continue;
}
if (_territory.get(terr) == null)
{
final L2Territory t = new L2Territory(terr);
_territory.put(terr, t);
}
_territory.get(terr).add(row[1], row[2], row[3], row[4], row[5]);
}
}
}

View File

@@ -0,0 +1,488 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import org.mmocore.network.ReceivablePacket;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.network.L2GameClient;
import javolution.text.TextBuilder;
/**
* <p>
* This class is made to handle all the ThreadPools used in L2j.
* </p>
* <p>
* Scheduled Tasks can either be sent to a {@link #_generalScheduledThreadPool "general"} or {@link #_effectsScheduledThreadPool "effects"} {@link ScheduledThreadPoolExecutor ScheduledThreadPool}: The "effects" one is used for every effects (skills, hp/mp regen ...) while the "general" one is used
* for everything else that needs to be scheduled.<br>
* There also is an {@link #_aiScheduledThreadPool "ai"} {@link ScheduledThreadPoolExecutor ScheduledThreadPool} used for AI Tasks.
* </p>
* <p>
* Tasks can be sent to {@link ScheduledThreadPoolExecutor ScheduledThreadPool} either with:
* <ul>
* <li>{@link #scheduleEffect(Runnable, long)} : for effects Tasks that needs to be executed only once.</li>
* <li>{@link #scheduleGeneral(Runnable, long)} : for scheduled Tasks that needs to be executed once.</li>
* <li>{@link #scheduleAi(Runnable, long)} : for AI Tasks that needs to be executed once</li>
* </ul>
* </p>
* <p>
* For all Tasks that should be executed with no delay asynchronously in a ThreadPool there also are usual {@link ThreadPoolExecutor ThreadPools} that can grow/shrink according to their load.:
* <ul>
* <li>{@link #_generalPacketsThreadPool GeneralPackets} where most packets handler are executed.</li>
* <li>{@link #_ioPacketsThreadPool I/O Packets} where all the i/o packets are executed.</li>
* <li>There will be an AI ThreadPool where AI events should be executed</li>
* <li>A general ThreadPool where everything else that needs to run asynchronously with no delay should be executed ({@link com.l2jmobius.gameserver.model.actor.knownlist KnownList} updates, SQL updates/inserts...)?</li>
* </ul>
* </p>
* @author -Wooden-
*/
@SuppressWarnings("rawtypes")
public class ThreadPoolManager
{
protected static final Logger _log = Logger.getLogger(ThreadPoolManager.class.getName());
private static ThreadPoolManager _instance;
private final ScheduledThreadPoolExecutor _effectsScheduledThreadPool;
private final ScheduledThreadPoolExecutor _generalScheduledThreadPool;
private final ThreadPoolExecutor _generalPacketsThreadPool;
private final ThreadPoolExecutor _ioPacketsThreadPool;
// will be really used in the next AI implementation.
private final ThreadPoolExecutor _aiThreadPool;
private final ThreadPoolExecutor _generalThreadPool;
// temp
private final ScheduledThreadPoolExecutor _aiScheduledThreadPool;
/** temp workaround for VM issue */
private static final long MAX_DELAY = Long.MAX_VALUE / 1000000 / 2;
private boolean _shutdown;
public static ThreadPoolManager getInstance()
{
if (_instance == null)
{
_instance = new ThreadPoolManager();
}
return _instance;
}
private ThreadPoolManager()
{
_effectsScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.THREAD_P_EFFECTS, new PriorityThreadFactory("EffectsSTPool", Thread.NORM_PRIORITY));
_generalScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.THREAD_P_GENERAL, new PriorityThreadFactory("GerenalSTPool", Thread.NORM_PRIORITY));
_ioPacketsThreadPool = new ThreadPoolExecutor(Config.IO_PACKET_THREAD_CORE_SIZE, Integer.MAX_VALUE, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("I/O Packet Pool", Thread.NORM_PRIORITY + 1));
_generalPacketsThreadPool = new ThreadPoolExecutor(Config.GENERAL_PACKET_THREAD_CORE_SIZE, Config.GENERAL_PACKET_THREAD_CORE_SIZE + 2, 15L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("Normal Packet Pool", Thread.NORM_PRIORITY + 1));
_generalThreadPool = new ThreadPoolExecutor(Config.GENERAL_THREAD_CORE_SIZE, Config.GENERAL_THREAD_CORE_SIZE + 2, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("General Pool", Thread.NORM_PRIORITY));
// will be really used in the next AI implementation.
_aiThreadPool = new ThreadPoolExecutor(1, Config.AI_MAX_THREAD, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
_aiScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.AI_MAX_THREAD, new PriorityThreadFactory("AISTPool", Thread.NORM_PRIORITY));
}
public static long validateDelay(long delay)
{
if (delay < 0)
{
delay = 0;
}
else if (delay > MAX_DELAY)
{
delay = MAX_DELAY;
}
return delay;
}
public ScheduledFuture scheduleEffect(Runnable r, long delay)
{
try
{
delay = ThreadPoolManager.validateDelay(delay);
return _effectsScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
}
catch (final RejectedExecutionException e)
{
/* shutdown, ignore */
return null;
}
}
public ScheduledFuture scheduleEffectAtFixedRate(Runnable r, long initial, long delay)
{
try
{
delay = ThreadPoolManager.validateDelay(delay);
initial = ThreadPoolManager.validateDelay(initial);
return _effectsScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
}
catch (final RejectedExecutionException e)
{
/* shutdown, ignore */
return null;
}
}
public boolean removeEffect(Runnable r)
{
return _effectsScheduledThreadPool.remove(r);
}
public ScheduledFuture scheduleGeneral(Runnable r, long delay)
{
try
{
delay = ThreadPoolManager.validateDelay(delay);
return _generalScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
}
catch (final RejectedExecutionException e)
{
/* shutdown, ignore */
return null;
}
}
public ScheduledFuture scheduleGeneralAtFixedRate(Runnable r, long initial, long delay)
{
try
{
delay = ThreadPoolManager.validateDelay(delay);
initial = ThreadPoolManager.validateDelay(initial);
return _generalScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
}
catch (final RejectedExecutionException e)
{
/* shutdown, ignore */
return null;
}
}
public boolean removeGeneral(Runnable r)
{
return _generalScheduledThreadPool.remove(r);
}
public ScheduledFuture scheduleAi(Runnable r, long delay)
{
try
{
delay = ThreadPoolManager.validateDelay(delay);
return _aiScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
}
catch (final RejectedExecutionException e)
{
/* shutdown, ignore */
return null;
}
}
public ScheduledFuture scheduleAiAtFixedRate(Runnable r, long initial, long delay)
{
try
{
delay = ThreadPoolManager.validateDelay(delay);
initial = ThreadPoolManager.validateDelay(initial);
return _aiScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
}
catch (final RejectedExecutionException e)
{
/* shutdown, ignore */
return null;
}
}
public void executePacket(ReceivablePacket<L2GameClient> pkt)
{
_generalPacketsThreadPool.execute(pkt);
}
public void executeCommunityPacket(Runnable r)
{
_generalPacketsThreadPool.execute(r);
}
public void executeIOPacket(ReceivablePacket<L2GameClient> pkt)
{
_ioPacketsThreadPool.execute(pkt);
}
public void executeTask(Runnable r)
{
_generalThreadPool.execute(r);
}
public void executeAi(Runnable r)
{
_aiThreadPool.execute(r);
}
public String[] getStats()
{
return new String[]
{
"STP:",
" + Effects:",
" |- ActiveThreads: " + _effectsScheduledThreadPool.getActiveCount(),
" |- getCorePoolSize: " + _effectsScheduledThreadPool.getCorePoolSize(),
" |- PoolSize: " + _effectsScheduledThreadPool.getPoolSize(),
" |- MaximumPoolSize: " + _effectsScheduledThreadPool.getMaximumPoolSize(),
" |- CompletedTasks: " + _effectsScheduledThreadPool.getCompletedTaskCount(),
" |- ScheduledTasks: " + (_effectsScheduledThreadPool.getTaskCount() - _effectsScheduledThreadPool.getCompletedTaskCount()),
" | -------",
" + General:",
" |- ActiveThreads: " + _generalScheduledThreadPool.getActiveCount(),
" |- getCorePoolSize: " + _generalScheduledThreadPool.getCorePoolSize(),
" |- PoolSize: " + _generalScheduledThreadPool.getPoolSize(),
" |- MaximumPoolSize: " + _generalScheduledThreadPool.getMaximumPoolSize(),
" |- CompletedTasks: " + _generalScheduledThreadPool.getCompletedTaskCount(),
" |- ScheduledTasks: " + (_generalScheduledThreadPool.getTaskCount() - _generalScheduledThreadPool.getCompletedTaskCount()),
" | -------",
" + AI:",
" |- ActiveThreads: " + _aiScheduledThreadPool.getActiveCount(),
" |- getCorePoolSize: " + _aiScheduledThreadPool.getCorePoolSize(),
" |- PoolSize: " + _aiScheduledThreadPool.getPoolSize(),
" |- MaximumPoolSize: " + _aiScheduledThreadPool.getMaximumPoolSize(),
" |- CompletedTasks: " + _aiScheduledThreadPool.getCompletedTaskCount(),
" |- ScheduledTasks: " + (_aiScheduledThreadPool.getTaskCount() - _aiScheduledThreadPool.getCompletedTaskCount()),
"TP:",
" + Packets:",
" |- ActiveThreads: " + _generalPacketsThreadPool.getActiveCount(),
" |- getCorePoolSize: " + _generalPacketsThreadPool.getCorePoolSize(),
" |- MaximumPoolSize: " + _generalPacketsThreadPool.getMaximumPoolSize(),
" |- LargestPoolSize: " + _generalPacketsThreadPool.getLargestPoolSize(),
" |- PoolSize: " + _generalPacketsThreadPool.getPoolSize(),
" |- CompletedTasks: " + _generalPacketsThreadPool.getCompletedTaskCount(),
" |- QueuedTasks: " + _generalPacketsThreadPool.getQueue().size(),
" | -------",
" + I/O Packets:",
" |- ActiveThreads: " + _ioPacketsThreadPool.getActiveCount(),
" |- getCorePoolSize: " + _ioPacketsThreadPool.getCorePoolSize(),
" |- MaximumPoolSize: " + _ioPacketsThreadPool.getMaximumPoolSize(),
" |- LargestPoolSize: " + _ioPacketsThreadPool.getLargestPoolSize(),
" |- PoolSize: " + _ioPacketsThreadPool.getPoolSize(),
" |- CompletedTasks: " + _ioPacketsThreadPool.getCompletedTaskCount(),
" |- QueuedTasks: " + _ioPacketsThreadPool.getQueue().size(),
" | -------",
" + General Tasks:",
" |- ActiveThreads: " + _generalThreadPool.getActiveCount(),
" |- getCorePoolSize: " + _generalThreadPool.getCorePoolSize(),
" |- MaximumPoolSize: " + _generalThreadPool.getMaximumPoolSize(),
" |- LargestPoolSize: " + _generalThreadPool.getLargestPoolSize(),
" |- PoolSize: " + _generalThreadPool.getPoolSize(),
" |- CompletedTasks: " + _generalThreadPool.getCompletedTaskCount(),
" |- QueuedTasks: " + _generalThreadPool.getQueue().size(),
" | -------",
" + AI:",
" |- Not Done"
};
}
private class PriorityThreadFactory implements ThreadFactory
{
private final int _prio;
private final String _name;
private final AtomicInteger _threadNumber = new AtomicInteger(1);
private final ThreadGroup _group;
public PriorityThreadFactory(String name, int prio)
{
_prio = prio;
_name = name;
_group = new ThreadGroup(_name);
}
/*
* (non-Javadoc)
* @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
*/
@Override
public Thread newThread(Runnable r)
{
final Thread t = new Thread(_group, r);
t.setName(_name + "-" + _threadNumber.getAndIncrement());
t.setPriority(_prio);
return t;
}
public ThreadGroup getGroup()
{
return _group;
}
}
/**
*
*/
public void shutdown()
{
_shutdown = true;
try
{
_effectsScheduledThreadPool.awaitTermination(1, TimeUnit.SECONDS);
_generalScheduledThreadPool.awaitTermination(1, TimeUnit.SECONDS);
_generalPacketsThreadPool.awaitTermination(1, TimeUnit.SECONDS);
_ioPacketsThreadPool.awaitTermination(1, TimeUnit.SECONDS);
_generalThreadPool.awaitTermination(1, TimeUnit.SECONDS);
_aiThreadPool.awaitTermination(1, TimeUnit.SECONDS);
_effectsScheduledThreadPool.shutdown();
_generalScheduledThreadPool.shutdown();
_generalPacketsThreadPool.shutdown();
_ioPacketsThreadPool.shutdown();
_generalThreadPool.shutdown();
_aiThreadPool.shutdown();
_log.info("All ThreadPools are now stopped.");
}
catch (final InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean isShutdown()
{
return _shutdown;
}
/**
*
*/
public void purge()
{
_effectsScheduledThreadPool.purge();
_generalScheduledThreadPool.purge();
_aiScheduledThreadPool.purge();
_ioPacketsThreadPool.purge();
_generalPacketsThreadPool.purge();
_generalThreadPool.purge();
_aiThreadPool.purge();
}
public String getPacketStats()
{
final TextBuilder tb = new TextBuilder();
final ThreadFactory tf = _generalPacketsThreadPool.getThreadFactory();
if (tf instanceof PriorityThreadFactory)
{
tb.append("General Packet Thread Pool:\r\n");
tb.append("Tasks in the queue: " + _generalPacketsThreadPool.getQueue().size() + "\r\n");
tb.append("Showing threads stack trace:\r\n");
final PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
final int count = ptf.getGroup().activeCount();
final Thread[] threads = new Thread[count + 2];
ptf.getGroup().enumerate(threads);
tb.append("There should be " + count + " Threads\r\n");
for (final Thread t : threads)
{
if (t == null)
{
continue;
}
tb.append(t.getName() + "\r\n");
for (final StackTraceElement ste : t.getStackTrace())
{
tb.append(ste.toString());
tb.append("\r\n");
}
}
}
tb.append("Packet Tp stack traces printed.\r\n");
return tb.toString();
}
public String getIOPacketStats()
{
final TextBuilder tb = new TextBuilder();
final ThreadFactory tf = _ioPacketsThreadPool.getThreadFactory();
if (tf instanceof PriorityThreadFactory)
{
tb.append("I/O Packet Thread Pool:\r\n");
tb.append("Tasks in the queue: " + _ioPacketsThreadPool.getQueue().size() + "\r\n");
tb.append("Showing threads stack trace:\r\n");
final PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
final int count = ptf.getGroup().activeCount();
final Thread[] threads = new Thread[count + 2];
ptf.getGroup().enumerate(threads);
tb.append("There should be " + count + " Threads\r\n");
for (final Thread t : threads)
{
if (t == null)
{
continue;
}
tb.append(t.getName() + "\r\n");
for (final StackTraceElement ste : t.getStackTrace())
{
tb.append(ste.toString());
tb.append("\r\n");
}
}
}
tb.append("Packet Tp stack traces printed.\r\n");
return tb.toString();
}
public String getGeneralStats()
{
final TextBuilder tb = new TextBuilder();
final ThreadFactory tf = _generalThreadPool.getThreadFactory();
if (tf instanceof PriorityThreadFactory)
{
tb.append("General Thread Pool:\r\n");
tb.append("Tasks in the queue: " + _generalThreadPool.getQueue().size() + "\r\n");
tb.append("Showing threads stack trace:\r\n");
final PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
final int count = ptf.getGroup().activeCount();
final Thread[] threads = new Thread[count + 2];
ptf.getGroup().enumerate(threads);
tb.append("There should be " + count + " Threads\r\n");
for (final Thread t : threads)
{
if (t == null)
{
continue;
}
tb.append(t.getName() + "\r\n");
for (final StackTraceElement ste : t.getStackTrace())
{
tb.append(ste.toString());
tb.append("\r\n");
}
}
}
tb.append("Packet Tp stack traces printed.\r\n");
return tb.toString();
}
}

View File

@@ -0,0 +1,337 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.L2ItemInstance;
import com.l2jmobius.gameserver.model.L2TradeList;
import javolution.util.FastList;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.5.4.13 $ $Date: 2005/04/06 16:13:38 $
*/
public class TradeController
{
private static Logger _log = Logger.getLogger(TradeController.class.getName());
private static TradeController _instance;
private int _nextListId;
private final Map<Integer, L2TradeList> _lists;
public static TradeController getInstance()
{
if (_instance == null)
{
_instance = new TradeController();
}
return _instance;
}
private TradeController()
{
_lists = new FastMap<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement1 = con.prepareStatement("SELECT shop_id, npc_id FROM merchant_shopids");
ResultSet rset1 = statement1.executeQuery())
{
int itemId, price, count, currentCount, time;
long saveTime;
while (rset1.next())
{
try (
PreparedStatement statement = con.prepareStatement("SELECT item_id, price, shop_id, " + L2DatabaseFactory.getInstance().safetyString("order") + ", count, currentCount, time, savetimer FROM merchant_buylists WHERE shop_id=? ORDER BY " + L2DatabaseFactory.getInstance().safetyString("order") + " ASC"))
{
statement.setString(1, String.valueOf(rset1.getInt("shop_id")));
try (ResultSet rset = statement.executeQuery())
{
final L2TradeList buy1 = new L2TradeList(rset1.getInt("shop_id"));
while (rset.next())
{
itemId = rset.getInt("item_id");
price = rset.getInt("price");
count = rset.getInt("count");
currentCount = rset.getInt("currentCount");
time = rset.getInt("time");
saveTime = rset.getLong("savetimer");
final L2ItemInstance item = ItemTable.getInstance().createDummyItem(itemId);
if (item == null)
{
_log.warning("Skipping itemId: " + itemId + " on buylistId: " + buy1.getListId() + ", missing data for that item.");
continue;
}
if (price <= -1)
{
price = item.getItem().getReferencePrice();
}
if (Config.DEBUG)
{
// debug
final double diff = ((double) (price)) / item.getItem().getReferencePrice();
if ((diff < 0.8) || (diff > 1.2))
{
_log.severe("PRICING DEBUG: TradeListId: " + buy1.getListId() + " - ItemId: " + itemId + " (" + item.getItem().getName() + ") diff: " + diff + " - Price: " + price + " - Reference: " + item.getItem().getReferencePrice());
}
}
if (count > -1)
{
item.setCountDecrease(true);
}
item.setPriceToSell(price);
item.setInitCount(count);
if (currentCount > -1)
{
item.setCount(currentCount);
}
else
{
item.setCount(count);
}
item.setTime(time);
if (item.getTime() > 0)
{
item.setRestoreTime(saveTime);
}
buy1.addItem(item);
buy1.setNpcId(rset1.getString("npc_id"));
_lists.put(new Integer(buy1.getListId()), buy1);
_nextListId = Math.max(_nextListId, buy1.getListId() + 1);
}
}
}
}
_log.config("TradeController: Loaded " + _lists.size() + " Buylists.");
}
catch (final Exception e)
{
_log.warning("TradeController: Buylists could not be initialized.");
e.printStackTrace();
}
/*
* If enabled, initialize the custom buylist
*/
if (Config.CUSTOM_MERCHANT_TABLES)
{
final int initialSize = _lists.size();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement1 = con.prepareStatement("SELECT shop_id, npc_id FROM custom_merchant_shopids");
ResultSet rset1 = statement1.executeQuery())
{
int itemId, price, count, currentCount, time;
long saveTime;
while (rset1.next())
{
try (
PreparedStatement statement = con.prepareStatement("SELECT item_id, price, shop_id, " + L2DatabaseFactory.getInstance().safetyString("order") + ", count, currentCount, time, savetimer FROM custom_merchant_buylists WHERE shop_id=? ORDER BY " + L2DatabaseFactory.getInstance().safetyString("order") + " ASC"))
{
statement.setString(1, String.valueOf(rset1.getInt("shop_id")));
try (ResultSet rset = statement.executeQuery())
{
final L2TradeList buy1 = new L2TradeList(rset1.getInt("shop_id"));
while (rset.next())
{
itemId = rset.getInt("item_id");
price = rset.getInt("price");
count = rset.getInt("count");
currentCount = rset.getInt("currentCount");
time = rset.getInt("time");
saveTime = rset.getLong("savetimer");
final L2ItemInstance item = ItemTable.getInstance().createDummyItem(itemId);
if (item == null)
{
_log.warning("Skipping itemId: " + itemId + " on buylistId: " + buy1.getListId() + ", missing data for that item.");
continue;
}
if (price <= -1)
{
price = item.getItem().getReferencePrice();
}
if (Config.DEBUG)
{
// debug
final double diff = ((double) (price)) / item.getItem().getReferencePrice();
if ((diff < 0.8) || (diff > 1.2))
{
_log.severe("PRICING DEBUG: TradeListId: " + buy1.getListId() + " - ItemId: " + itemId + " (" + item.getItem().getName() + ") diff: " + diff + " - Price: " + price + " - Reference: " + item.getItem().getReferencePrice());
}
}
if (count > -1)
{
item.setCountDecrease(true);
}
item.setPriceToSell(price);
item.setInitCount(count);
if (currentCount > -1)
{
item.setCount(currentCount);
}
else
{
item.setCount(count);
}
item.setTime(time);
if (item.getTime() > 0)
{
item.setRestoreTime(saveTime);
}
buy1.addItem(item);
buy1.setNpcId(rset1.getString("npc_id"));
_lists.put(new Integer(buy1.getListId()), buy1);
_nextListId = Math.max(_nextListId, buy1.getListId() + 1);
}
}
}
}
_log.config("TradeController: Loaded " + (_lists.size() - initialSize) + " Custom Buylists.");
}
catch (final Exception e)
{
_log.warning("TradeController: Custom Buylists could not be initialized.");
e.printStackTrace();
}
}
}
// private int parseList(String line)
// {
// int itemCreated = 0;
// StringTokenizer st = new StringTokenizer(line, ";");
// int listId = Integer.parseInt(st.nextToken());
// L2TradeList buy1 = new L2TradeList(listId);
// while (st.hasMoreTokens())
// {
// int itemId = Integer.parseInt(st.nextToken());
// int price = Integer.parseInt(st.nextToken());
//
// L2ItemInstance item = ItemTable.getInstance().createDummyItem(itemId);
// item.setPriceToSell(price);
// buy1.addItem(item);
// itemCreated++;
// }
// _lists.put(new Integer(buy1.getListId()), buy1);
// return itemCreated;
// }
public L2TradeList getBuyList(int listId)
{
return _lists.get(new Integer(listId));
}
public List<L2TradeList> getBuyListByNpcId(int npcId)
{
final List<L2TradeList> lists = new FastList<>();
for (final L2TradeList list : _lists.values())
{
if (list.getNpcId().startsWith("gm"))
{
continue;
}
if (npcId == Integer.parseInt(list.getNpcId()))
{
lists.add(list);
}
}
return lists;
}
public void dataCountStore()
{
int listId;
if (_lists == null)
{
return;
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
for (final L2TradeList list : _lists.values())
{
listId = list.getListId();
// if (list == null)
// {
// continue;
// }
for (final L2ItemInstance Item : list.getItems())
{
if (Item.getCount() < Item.getInitCount())
{
try (PreparedStatement statement = con.prepareStatement("UPDATE merchant_buylists SET currentCount =? WHERE item_id =? && shop_id = ?"))
{
statement.setInt(1, Item.getCount());
statement.setInt(2, Item.getItemId());
statement.setInt(3, listId);
statement.executeUpdate();
}
}
}
}
}
catch (final Exception e)
{
_log.log(Level.SEVERE, "TradeController: Could not store Count Item");
}
}
/**
* @return
*/
public synchronized int getNextId()
{
return _nextListId++;
}
}

View File

@@ -0,0 +1,525 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import javax.imageio.ImageIO;
import com.l2jmobius.Config;
@SuppressWarnings("rawtypes")
public class Universe implements Serializable
{
public static final int MIN_X = -127900;
public static final int MAX_X = 194327;
public static final int MIN_Y = -30000;
public static final int MAX_Y = 259536;
public static final int MIN_Z = -17000;
public static final int MAX_Z = 17000;
public static final int MIN_X_GRID = 60;
public static final int MIN_Y_GRID = 60;
public static final int MIN_Z_GRID = 60;
public static final int MIN_GRID = 360;
private static Universe _instance;
protected static Logger _log = Logger.getLogger(Universe.class.getName());
public static void main(String[] args)
{
final Universe u = new Universe();
u.load();
// u.removeDoubles();
u.implode(false);
}
private class Position implements Comparable, Serializable
{
int _x;
// int _flag;
int _y;
int _z;
// public Position(int x, int y, int z, int flag)
// {
// _x = x;
// _y = y;
// _z = z;
// _flag = flag;
// }
// public Position(L2CharPosition pos)
// {
// _x = pos.x;
// _y = pos.y;
// _z = pos.z;
// _flag = 0;
// }
// public L2CharPosition L2CP()
// {
// return new L2CharPosition(_x, _y, _z, 0);
// }
@Override
public int compareTo(Object obj)
{
final Position o = (Position) obj;
int res = Integer.valueOf(_x).compareTo(o._x);
if (res != 0)
{
return res;
}
res = Integer.valueOf(_y).compareTo(o._y);
if (res != 0)
{
return res;
}
res = Integer.valueOf(_z).compareTo(o._z);
return res;
}
// public String toString()
// {
// return String.valueOf(_x) + " " + _y + " " + _z + " " + _flag;
// }
}
private class Coord implements Comparable, java.io.Serializable
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = -558060332886829552L;
int _x;
int _y;
int _z;
public Coord(int x, int y, int z)
{
_x = x;
_y = y;
_z = z;
}
// public Coord(L2CharPosition pos)
// {
// _x = pos.x;
// _y = pos.y;
// _z = pos.z;
// }
@Override
public int compareTo(Object obj)
{
final Position o = (Position) obj;
int res = Integer.valueOf(_x).compareTo(o._x);
if (res != 0)
{
return res;
}
res = Integer.valueOf(_y).compareTo(o._y);
if (res != 0)
{
return res;
}
res = Integer.valueOf(_z).compareTo(o._z);
return res;
}
@Override
public String toString()
{
return String.valueOf(_x) + " " + _y + " " + _z;
}
}
protected List<Coord> coordList;
private final HashSet<Integer> _logPlayers;
private boolean _logAll = true;
public static Universe getInstance()
{
if ((_instance == null) && Config.ACTIVATE_POSITION_RECORDER)
{
_instance = new Universe();
}
return _instance;
}
private Universe()
{
coordList = new LinkedList<>();
_logPlayers = new HashSet<>();
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new UniverseDump(), 30000, 30000);
}
public void registerHeight(int x, int y, int z)
{
// don't overwrite obstacle entries
// Position p = new Position(x, y, z, 0);
// _map.add(p);
coordList.add(new Coord(x, y, z));
// if (Config.USE_3D_MAP) insertInto3DMap(p);
}
public void registerObstacle(int x, int y, int z)
{
// Position p = new Position(x, y, z, -1);
// _map.add(p);
coordList.add(new Coord(x, y, z));
// if (Config.USE_3D_MAP) insertInto3DMap(p);
}
public boolean shouldLog(Integer id)
{
return (_logPlayers.contains(id) || _logAll);
}
public void setLogAll(boolean flag)
{
_logAll = flag;
}
public void addLogPlayer(Integer id)
{
_logPlayers.add(id);
_logAll = false;
}
public void removeLogPlayer(Integer id)
{
_logPlayers.remove(id);
}
public void loadAscii()
{
final int initialSize = coordList.size();
try (FileReader fr = new FileReader("data/universe.txt");
BufferedReader r = new BufferedReader(fr))
{
String line;
while ((line = r.readLine()) != null)
{
final StringTokenizer st = new StringTokenizer(line);
final String x1 = st.nextToken();
final String y1 = st.nextToken();
final String z1 = st.nextToken();
// String f1 = st.nextToken();
final int x = Integer.parseInt(x1);
final int y = Integer.parseInt(y1);
final int z = Integer.parseInt(z1);
// int f = Integer.parseInt(f1);
coordList.add(new Coord(x, y, z));
}
_log.info((coordList.size() - initialSize) + " additional nodes loaded from text file.");
}
catch (final Exception e)
{
_log.info("could not read text file universe.txt");
}
}
public void createMap()
{
final int zoom = 100;
final int w = (MAX_X - MIN_X) / zoom;
final int h = (MAX_Y - MIN_Y) / zoom;
final BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_GRAY);
final Graphics2D gr = bi.createGraphics();
int min_z = 0, max_z = 0;
for (final Coord pos : coordList)
{
if (pos == null)
{
continue;
}
if (pos._z < min_z)
{
min_z = pos._z;
}
if (pos._z > max_z)
{
max_z = pos._z;
}
}
for (final Coord pos : coordList)
{
if (pos == null)
{
continue;
}
final int x = (pos._x - MIN_X) / zoom;
final int y = (pos._y - MIN_Y) / zoom;
final int color = (int) ((((long) pos._z - MIN_Z) * 0xFFFFFF) / (MAX_Z - MIN_Z));
gr.setColor(new Color(color));
gr.drawLine(x, y, x, y);
}
try
{
ImageIO.write(bi, "png", new File("universe.png"));
}
catch (final Exception e)
{
_log.warning("cannot create universe.png: " + e);
}
}
public class UniverseFilter implements FilenameFilter
{
String ext = "";
public UniverseFilter(String pExt)
{
ext = pExt;
}
/*
* (non-Javadoc)
* @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
*/
@Override
public boolean accept(File arg0, String name)
{
return name.startsWith("universe") && name.endsWith("." + ext);
}
}
public void load()
{
final int total = 0;
if (coordList == null)
{
coordList = new LinkedList<>();
}
try
{
loadBinFiles();
loadHexFiles();
loadFinFiles();
_log.info(coordList.size() + " map vertices loaded in total.");
}
catch (final Exception e)
{
e.printStackTrace();
}
System.out.println("Total: " + total);
}
/**
* @throws FileNotFoundException
* @throws IOException
*/
private void loadFinFiles() throws FileNotFoundException, IOException
{
final FilenameFilter filter = new UniverseFilter("fin");
final File directory = new File("data");
final File[] files = directory.listFiles(filter);
for (final File file : files)
{
final List<Coord> newMap = new LinkedList<>();
// Save to file
try (FileInputStream fos = new FileInputStream(file);
DataInputStream data = new DataInputStream(fos))
{
final int count = data.readInt();
for (int i = 0; i < count; i++)
{
newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
}
}
_log.info(newMap.size() + " map vertices loaded from file " + file.getName());
coordList.addAll(newMap);
}
}
/**
* @throws FileNotFoundException
* @throws IOException
*/
private void loadHexFiles() throws FileNotFoundException, IOException
{
final FilenameFilter filter = new UniverseFilter("hex");
final File directory = new File("data");
final File[] files = directory.listFiles(filter);
for (final File file : files)
{
final List<Coord> newMap = new LinkedList<>();
// Save to file
try (FileInputStream fos = new FileInputStream(file);
GZIPInputStream gzos = new GZIPInputStream(fos);
DataInputStream data = new DataInputStream(gzos))
{
final int count = data.readInt();
for (int i = 0; i < count; i++)
{
newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
data.readInt();
}
}
_log.info(newMap.size() + " map vertices loaded from file " + file.getName());
coordList.addAll(newMap);
}
}
/**
* @throws FileNotFoundException
* @throws IOException
* @throws ClassNotFoundException
*/
@SuppressWarnings(value =
{
"unchecked"
})
private void loadBinFiles() throws FileNotFoundException, IOException, ClassNotFoundException
{
final FilenameFilter filter = new UniverseFilter("bin");
final File directory = new File("data");
final File[] files = directory.listFiles(filter);
for (final File file : files)
{
// Create necessary input streams
try (FileInputStream fis = new FileInputStream(file);
GZIPInputStream gzis = new GZIPInputStream(fis);
ObjectInputStream in = new ObjectInputStream(gzis))
{
// Read in an object. It should be a vector of scribbles
final TreeSet<Position> temp = (TreeSet<Position>) in.readObject();
_log.info(temp.size() + " map vertices loaded from file " + file.getName());
for (final Position p : temp)
{
coordList.add(new Coord(p._x, p._y, p._z));
}
}
}
}
public class UniverseDump implements Runnable
{
/*
* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run()
{
final int size = coordList.size();
if (size > 100000)
{
flush();
}
}
}
public void flush()
{
// System.out.println("Size of dump: "+coordList.size());
final List<Coord> oldMap = coordList;
coordList = new LinkedList<>();
final int size = oldMap.size();
dump(oldMap, true);
_log.info("Universe Map : Dumped " + size + " vertices.");
}
public int size()
{
int size = 0;
if (coordList != null)
{
size = coordList.size();
}
return size;
}
public void dump(List<Coord> _map, boolean b)
{
String pad = "";
if (b)
{
pad = "" + System.currentTimeMillis();
}
try (FileOutputStream fos = new FileOutputStream("data/universe" + pad + ".fin"); // Save to file
DataOutputStream data = new DataOutputStream(fos))
{
final int count = _map.size();
data.writeInt(count);
for (final Coord p : _map)
{
if (p != null)
{
data.writeInt(p._x);
data.writeInt(p._y);
data.writeInt(p._z);
}
}
data.flush();
_log.info("Universe Map saved to: " + "data/universe" + pad + ".fin");
}
catch (final Exception e)
{
e.printStackTrace();
}
}
// prepare for shutdown
public void implode(boolean b)
{
createMap();
dump(coordList, b);
}
}

View File

@@ -0,0 +1,859 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.GameTimeController;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.L2CharPosition;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import com.l2jmobius.gameserver.network.serverpackets.AutoAttackStart;
import com.l2jmobius.gameserver.network.serverpackets.AutoAttackStop;
import com.l2jmobius.gameserver.network.serverpackets.CharMoveToLocation;
import com.l2jmobius.gameserver.network.serverpackets.Die;
import com.l2jmobius.gameserver.network.serverpackets.MoveToPawn;
import com.l2jmobius.gameserver.network.serverpackets.StopMove;
import com.l2jmobius.gameserver.network.serverpackets.StopRotation;
import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
/**
* Mother class of all objects AI in the world.<BR>
* <BR>
* AbastractAI :<BR>
* <BR>
* <li>L2CharacterAI</li><BR>
* <BR>
*/
abstract class AbstractAI implements Ctrl
{
protected static final Logger _log = Logger.getLogger(AbstractAI.class.getName());
class FollowTask implements Runnable
{
int _range = 70;
public FollowTask()
{
}
public FollowTask(int range)
{
_range = range;
}
@Override
public void run()
{
try
{
if (_follow_task == null)
{
return;
}
if (_follow_target == null)
{
if (_actor instanceof L2Summon)
{
((L2Summon) _actor).setFollowStatus(false);
}
setIntention(AI_INTENTION_IDLE);
return;
}
if (!_actor.isInsideRadius(_follow_target, _range, true, false))
{
if (!_actor.isInsideRadius(_follow_target, 3000, true, false))
{
// if the target is too far (maybe also teleported)
if (_actor instanceof L2Summon)
{
((L2Summon) _actor).setFollowStatus(false);
}
setIntention(AI_INTENTION_IDLE);
return;
}
moveToPawn(_follow_target, _range);
}
}
catch (final Throwable t)
{
_log.log(Level.WARNING, "", t);
}
}
}
/** The character that this AI manages */
final L2Character _actor;
/** An accessor for private methods of the actor */
final L2Character.AIAccessor _accessor;
/** Current long-term intention */
protected CtrlIntention _intention = AI_INTENTION_IDLE;
/** Current long-term intention parameter */
protected Object _intention_arg0 = null;
/** Current long-term intention parameter */
protected Object _intention_arg1 = null;
/** Flags about client's state, in order to know which messages to send */
protected boolean _client_moving;
/** Flags about client's state, in order to know which messages to send */
protected boolean _client_auto_attacking;
/** Flags about client's state, in order to know which messages to send */
protected int _client_moving_to_pawn_offset;
/** Different targets this AI maintains */
private L2Object _target;
private L2Character _cast_target;
protected L2Character _attack_target;
protected L2Character _follow_target;
/** The skill we are curently casting by INTENTION_CAST */
L2Skill _skill;
/** Diferent internal state flags */
private int _move_to_pawn_timeout;
protected Future<?> _follow_task = null;
private static final int FOLLOW_INTERVAL = 1000;
private static final int ATTACK_FOLLOW_INTERVAL = 500;
/**
* Constructor of AbstractAI.<BR>
* <BR>
* @param accessor The AI accessor of the L2Character
*/
protected AbstractAI(L2Character.AIAccessor accessor)
{
_accessor = accessor;
// Get the L2Character managed by this Accessor AI
_actor = accessor.getActor();
}
/**
* Return the L2Character managed by this Accessor AI.<BR>
* <BR>
*/
@Override
public L2Character getActor()
{
return _actor;
}
/**
* Return the current Intention.<BR>
* <BR>
*/
@Override
public CtrlIntention getIntention()
{
return _intention;
}
protected synchronized void setCastTarget(L2Character target)
{
_cast_target = target;
}
/**
* Return the current cast target.<BR>
* <BR>
* @return
*/
public L2Character getCastTarget()
{
return _cast_target;
}
protected synchronized void setAttackTarget(L2Character target)
{
_attack_target = target;
}
/**
* Return current attack target.<BR>
* <BR>
*/
@Override
public L2Character getAttackTarget()
{
return _attack_target;
}
/**
* Set the Intention of this AbstractAI.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : This method is USED by AI classes</B></FONT><BR>
* <BR>
* <B><U> Overriden in </U> : </B><BR>
* <B>L2AttackableAI</B> : Create an AI Task executed every 1s (if necessary)<BR>
* <B>L2PlayerAI</B> : Stores the current AI intention parameters to later restore it if necessary<BR>
* <BR>
* @param intention The new Intention to set to the AI
* @param arg0 The first parameter of the Intention
* @param arg1 The second parameter of the Intention
*/
synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
{
/*
* if (Config.DEBUG) _log.warning("AbstractAI: changeIntention -> " + intention + " " + arg0 + " " + arg1);
*/
_intention = intention;
_intention_arg0 = arg0;
_intention_arg1 = arg1;
}
/**
* Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR>
* <BR>
* @param intention The new Intention to set to the AI
*/
@Override
public final void setIntention(CtrlIntention intention)
{
setIntention(intention, null, null);
}
/**
* Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR>
* <BR>
* @param intention The new Intention to set to the AI
* @param arg0 The first parameter of the Intention (optional target)
*/
@Override
public final void setIntention(CtrlIntention intention, Object arg0)
{
setIntention(intention, arg0, null);
}
/**
* Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR>
* <BR>
* @param intention The new Intention to set to the AI
* @param arg0 The first parameter of the Intention (optional target)
* @param arg1 The second parameter of the Intention (optional target)
*/
@Override
public final void setIntention(CtrlIntention intention, Object arg0, Object arg1)
{
if (_actor instanceof L2PcInstance)
{
if (((L2PcInstance) _actor).isPendingSitting())
{
((L2PcInstance) _actor).setIsPendingSitting(false);
}
}
// Stop the follow mode if necessary
if ((intention != AI_INTENTION_FOLLOW) && (intention != AI_INTENTION_ATTACK))
{
stopFollow();
}
// Launch the onIntention method of the L2CharacterAI corresponding to the new Intention
switch (intention)
{
case AI_INTENTION_IDLE:
onIntentionIdle();
break;
case AI_INTENTION_ACTIVE:
onIntentionActive();
break;
case AI_INTENTION_REST:
onIntentionRest();
break;
case AI_INTENTION_ATTACK:
onIntentionAttack((L2Character) arg0);
break;
case AI_INTENTION_CAST:
onIntentionCast((L2Skill) arg0, (L2Object) arg1);
break;
case AI_INTENTION_MOVE_TO:
onIntentionMoveTo((L2CharPosition) arg0);
break;
case AI_INTENTION_FOLLOW:
onIntentionFollow((L2Character) arg0);
break;
case AI_INTENTION_PICK_UP:
onIntentionPickUp((L2Object) arg0);
break;
case AI_INTENTION_INTERACT:
onIntentionInteract((L2Object) arg0);
break;
}
}
/**
* Launch the L2CharacterAI onEvt method corresponding to the Event.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change (ex : If the character attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR>
* <BR>
* @param evt The event whose the AI must be notified
*/
@Override
public final void notifyEvent(CtrlEvent evt)
{
notifyEvent(evt, null, null);
}
/**
* Launch the L2CharacterAI onEvt method corresponding to the Event.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change (ex : If the character attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR>
* <BR>
* @param evt The event whose the AI must be notified
* @param arg0 The first parameter of the Event (optional target)
*/
@Override
public final void notifyEvent(CtrlEvent evt, Object arg0)
{
notifyEvent(evt, arg0, null);
}
/**
* Launch the L2CharacterAI onEvt method corresponding to the Event.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change (ex : If the character attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR>
* <BR>
* @param evt The event whose the AI must be notified
* @param arg0 The first parameter of the Event (optional target)
* @param arg1 The second parameter of the Event (optional target)
*/
@Override
public final void notifyEvent(CtrlEvent evt, Object arg0, Object arg1)
{
if (!_actor.isVisible() || !_actor.hasAI())
{
return;
}
switch (evt)
{
case EVT_THINK:
onEvtThink();
break;
case EVT_ATTACKED:
onEvtAttacked((L2Character) arg0);
break;
case EVT_AGGRESSION:
onEvtAggression((L2Character) arg0, ((Number) arg1).intValue());
break;
case EVT_STUNNED:
onEvtStunned((L2Character) arg0);
break;
case EVT_PARALYZED:
onEvtParalyzed((L2Character) arg0);
break;
case EVT_SLEEPING:
onEvtSleeping((L2Character) arg0);
break;
case EVT_ROOTED:
onEvtRooted((L2Character) arg0);
break;
case EVT_CONFUSED:
onEvtConfused((L2Character) arg0);
break;
case EVT_MUTED:
onEvtMuted((L2Character) arg0);
break;
case EVT_READY_TO_ACT:
onEvtReadyToAct();
break;
case EVT_USER_CMD:
onEvtUserCmd(arg0, arg1);
break;
case EVT_ARRIVED:
onEvtArrived();
break;
case EVT_ARRIVED_REVALIDATE:
onEvtArrivedRevalidate();
break;
case EVT_ARRIVED_BLOCKED:
onEvtArrivedBlocked((L2CharPosition) arg0);
break;
case EVT_FORGET_OBJECT:
onEvtForgetObject((L2Object) arg0);
break;
case EVT_CANCEL:
onEvtCancel();
break;
case EVT_DEAD:
onEvtDead();
break;
case EVT_FAKE_DEATH:
onEvtFakeDeath();
break;
case EVT_FINISH_CASTING:
onEvtFinishCasting();
break;
}
}
protected abstract void onIntentionIdle();
protected abstract void onIntentionActive();
protected abstract void onIntentionRest();
protected abstract void onIntentionAttack(L2Character target);
protected abstract void onIntentionCast(L2Skill skill, L2Object target);
protected abstract void onIntentionMoveTo(L2CharPosition destination);
protected abstract void onIntentionFollow(L2Character target);
protected abstract void onIntentionPickUp(L2Object item);
protected abstract void onIntentionInteract(L2Object object);
protected abstract void onEvtThink();
protected abstract void onEvtAttacked(L2Character attacker);
protected abstract void onEvtAggression(L2Character target, int aggro);
protected abstract void onEvtStunned(L2Character attacker);
protected abstract void onEvtParalyzed(L2Character attacker);
protected abstract void onEvtSleeping(L2Character attacker);
protected abstract void onEvtRooted(L2Character attacker);
protected abstract void onEvtConfused(L2Character attacker);
protected abstract void onEvtMuted(L2Character attacker);
protected abstract void onEvtReadyToAct();
protected abstract void onEvtUserCmd(Object arg0, Object arg1);
protected abstract void onEvtArrived();
protected abstract void onEvtArrivedRevalidate();
protected abstract void onEvtArrivedBlocked(L2CharPosition blocked_at_pos);
protected abstract void onEvtForgetObject(L2Object object);
protected abstract void onEvtCancel();
protected abstract void onEvtDead();
protected abstract void onEvtFakeDeath();
protected abstract void onEvtFinishCasting();
/**
* Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
*/
protected void clientActionFailed()
{
if (_actor instanceof L2PcInstance)
{
_actor.sendPacket(new ActionFailed());
}
}
/**
* Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn <I>(broadcast)</I>.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
* @param pawn
* @param offset
*/
protected void moveToPawn(L2Object pawn, int offset)
{
// Chek if actor can move
if (!_actor.isMovementDisabled())
{
if (offset < 10)
{
offset = 10;
}
// prevent possible extra calls to this function (there is none?),
// also don't send movetopawn packets too often
boolean sendPacket = true;
if (_client_moving && (_target == pawn))
{
if (_client_moving_to_pawn_offset == offset)
{
if (GameTimeController.getGameTicks() < _move_to_pawn_timeout)
{
return;
}
sendPacket = false;
}
else if (_actor.isOnGeodataPath())
{
// minimum time to calculate new route is 2 seconds
if (GameTimeController.getGameTicks() < (_move_to_pawn_timeout + 10))
{
return;
}
}
}
// Set AI movement data
_client_moving = true;
_client_moving_to_pawn_offset = offset;
_target = pawn;
_move_to_pawn_timeout = GameTimeController.getGameTicks();
_move_to_pawn_timeout += 1000 / GameTimeController.MILLIS_IN_TICK;
if ((pawn == null) || (_accessor == null))
{
return;
}
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_accessor.moveTo(pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving())
{
_actor.sendPacket(new ActionFailed());
return;
}
// Send a Server->Client packet MoveToPawn/CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
if (pawn instanceof L2Character)
{
if (_actor.isOnGeodataPath())
{
_actor.broadcastPacket(new CharMoveToLocation(_actor));
_client_moving_to_pawn_offset = 0;
}
else if (sendPacket)
{
_actor.broadcastPacket(new MoveToPawn(_actor, (L2Character) pawn, offset));
}
}
else
{
_actor.broadcastPacket(new CharMoveToLocation(_actor));
}
}
else
{
_actor.sendPacket(new ActionFailed());
}
}
/**
* Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation <I>(broadcast)</I>.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
* @param x
* @param y
* @param z
*/
protected void moveTo(int x, int y, int z)
{
// Chek if actor can move
if (!_actor.isMovementDisabled())
{
// Set AI movement data
_client_moving = true;
_client_moving_to_pawn_offset = 0;
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_accessor.moveTo(x, y, z);
// Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
final CharMoveToLocation msg = new CharMoveToLocation(_actor);
_actor.broadcastPacket(msg);
}
else
{
_actor.sendPacket(new ActionFailed());
}
}
/**
* Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation <I>(broadcast)</I>.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
* @param pos
*/
protected void clientStopMoving(L2CharPosition pos)
{
// Stop movement of the L2Character
if (_actor.isMoving())
{
_accessor.stopMove(pos);
}
_client_moving_to_pawn_offset = 0;
if (_client_moving || (pos != null))
{
_client_moving = false;
// Send a Server->Client packet StopMove to the actor and all L2PcInstance in its _knownPlayers
final StopMove msg = new StopMove(_actor);
_actor.broadcastPacket(msg);
if (pos != null)
{
// Send a Server->Client packet StopRotation to the actor and all L2PcInstance in its _knownPlayers
final StopRotation sr = new StopRotation(_actor.getObjectId(), pos.heading, 0);
_actor.sendPacket(sr);
_actor.broadcastPacket(sr);
}
}
}
// Client has already arrived to target, no need to force StopMove packet
protected void clientStoppedMoving()
{
if (_client_moving_to_pawn_offset > 0)
{
_client_moving_to_pawn_offset = 0;
_actor.broadcastPacket(new StopMove(_actor));
}
_client_moving = false;
}
public boolean isAutoAttacking()
{
return _client_auto_attacking;
}
public void setAutoAttacking(boolean isAutoAttacking)
{
if (_actor instanceof L2Summon)
{
final L2Summon summon = (L2Summon) _actor;
if (summon.getOwner() != null)
{
summon.getOwner().getAI().setAutoAttacking(isAutoAttacking);
}
return;
}
_client_auto_attacking = isAutoAttacking;
}
/**
* Start the actor Auto Attack client side by sending Server->Client packet AutoAttackStart <I>(broadcast)</I>.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
*/
public void clientStartAutoAttack()
{
if (_actor instanceof L2Summon)
{
final L2Summon summon = (L2Summon) _actor;
if (summon.getOwner() != null)
{
summon.getOwner().getAI().clientStartAutoAttack();
}
return;
}
if (!isAutoAttacking())
{
if ((_actor instanceof L2PcInstance) && (((L2PcInstance) _actor).getPet() != null))
{
((L2PcInstance) _actor).getPet().broadcastPacket(new AutoAttackStart(((L2PcInstance) _actor).getPet().getObjectId()));
}
// Send a Server->Client packet AutoAttackStart to the actor and all L2PcInstance in its _knownPlayers
_actor.broadcastPacket(new AutoAttackStart(_actor.getObjectId()));
setAutoAttacking(true);
}
AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
}
/**
* Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop <I>(broadcast)</I>.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
*/
public void clientStopAutoAttack()
{
if (_actor instanceof L2Summon)
{
final L2Summon summon = (L2Summon) _actor;
if (summon.getOwner() != null)
{
summon.getOwner().getAI().clientStopAutoAttack();
}
return;
}
if (_actor instanceof L2PcInstance)
{
if (!AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor) && isAutoAttacking())
{
AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
}
}
else if (isAutoAttacking())
{
_actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
setAutoAttacking(false);
}
}
/**
* Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die <I>(broadcast)</I>.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
*/
protected void clientNotifyDead()
{
// Send a Server->Client packet Die to the actor and all L2PcInstance in its _knownPlayers
final Die msg = new Die(_actor);
_actor.broadcastPacket(msg);
// Init AI
_intention = AI_INTENTION_IDLE;
_target = null;
_cast_target = null;
_attack_target = null;
// Cancel the follow task if necessary
stopFollow();
}
/**
* Update the state of this actor client side by sending Server->Client packet MoveToPawn/CharMoveToLocation and AutoAttackStart to the L2PcInstance player.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
* <BR>
* @param player The L2PcIstance to notify with state of this L2Character
*/
public void describeStateToPlayer(L2PcInstance player)
{
if (_client_moving)
{
if ((_client_moving_to_pawn_offset != 0) && (_follow_target != null))
{
// Send a Server->Client packet MoveToPawn to the actor and all L2PcInstance in its _knownPlayers
final MoveToPawn msg = new MoveToPawn(_actor, _follow_target, _client_moving_to_pawn_offset);
player.sendPacket(msg);
}
else
{
// Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
final CharMoveToLocation msg = new CharMoveToLocation(_actor);
player.sendPacket(msg);
}
}
}
/**
* Create and Launch an AI Follow Task to execute every 1s.<BR>
* <BR>
* @param target The L2Character to follow
*/
public synchronized void startFollow(L2Character target)
{
if (_follow_task != null)
{
_follow_task.cancel(false);
_follow_task = null;
}
// Create and Launch an AI Follow Task to execute every 1s
_follow_target = target;
_follow_task = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new FollowTask(), 5, FOLLOW_INTERVAL);
}
/**
* Create and Launch an AI Follow Task to execute every 0.5s, following at specified range.<BR>
* <BR>
* @param target The L2Character to follow
* @param range
*/
public synchronized void startFollow(L2Character target, int range)
{
if (_follow_task != null)
{
_follow_task.cancel(false);
_follow_task = null;
}
_follow_target = target;
_follow_task = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new FollowTask(range), 5, ATTACK_FOLLOW_INTERVAL);
}
/**
* Stop an AI Follow Task.<BR>
* <BR>
*/
public synchronized void stopFollow()
{
if (_follow_task != null)
{
// Stop the Follow Task
_follow_task.cancel(false);
_follow_task = null;
}
_follow_target = null;
}
protected L2Character getFollowTarget()
{
return _follow_target;
}
protected L2Object getTarget()
{
return _target;
}
protected synchronized void setTarget(L2Object target)
{
_target = target;
}
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import com.l2jmobius.gameserver.model.L2Character;
/**
* Interface of AI and client state. To correctly send messages to client we need it's state. For example, if we've sent 'StartAutoAttack' message, we need to send 'StopAutoAttack' message before any other action. Or if we've sent 'MoveToPawn', we need to send 'StopMove' when the movement of a
* character is canceled (by Root spell or any other reason). Thus, we need to know the state of client, i.e. which messages we've sent and how the client will show the scene. Close to this task is the task of AI. If a player's character is attacking a mob, his ATTACK may be iterrupted by an event,
* that temporary disable attacking. But when the possibility to ATTACK will be enabled, the character must continue the ATTACK. For mobs it may be more complex, since we want them to decide when to use magic, or when to follow the player for physical combat, or when to escape, to help another mob,
* etc. This interface is hiding complexity of server<->client interaction and multiple states of a character. It allows to set a desired, simple "wish" of a character, and the implementation of this interface will take care about the rest. The goal of a character may be like "ATTACK", "random walk"
* and so on. To reach the goal inplementation will split it into several small actions, several steps (possibly repeatable). Like "run to target" then "hit it", then if target is not dead - repeat. This flow of simplier steps may be interrupted by incoming events. Like a character's movement was
* disabled (by Root spell, for instance). Depending on character's ability AI may choose to wait, or to use magic ATTACK and so on. Additionally incoming events are compared with client's state of the character, and required network messages are sent to client's, i.e. if we have incoming event that
* character's movement was disabled, it causes changing if its behavour, and if client's state for the character is "moving" we send messages to clients to stop the avatar/mob.
*/
public interface Ctrl
{
/**
* the character this AI serves
* @return
*/
L2Character getActor();
/**
* get current intention
* @return
*/
CtrlIntention getIntention();
/**
* get current ATTACK target
* @return
*/
L2Character getAttackTarget();
/**
* Set general state/intention for AI, with optional data
* @param intention
*/
void setIntention(CtrlIntention intention);
void setIntention(CtrlIntention intention, Object arg0);
void setIntention(CtrlIntention intention, Object arg0, Object arg1);
/**
* Event, that notifies about previous step result, or user command, that does not change current general intention
* @param evt
*/
void notifyEvent(CtrlEvent evt);
void notifyEvent(CtrlEvent evt, Object arg0);
void notifyEvent(CtrlEvent evt, Object arg0, Object arg1);
}

View File

@@ -0,0 +1,80 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
/**
* This class contains an enum of each possibles evenements that can happen on an AI character.
*/
public enum CtrlEvent
{
/**
* Something has changed, usually a previous step has being completed or maybe was completed, the AI must thing on next action
*/
EVT_THINK,
/**
* The actor was attacked. This event comes each time a physical or magical attack was done on the actor. NPC may start attack in responce, or ignore this event if they already attack someone, or change target and so on.
*/
EVT_ATTACKED,
/** Increase/decrease aggression towards a target, or reduce global aggression if target is null */
EVT_AGGRESSION,
/** Actor is in stun state */
EVT_STUNNED,
/** Actor is paralyzed or petrified */
EVT_PARALYZED,
/** Actor starts/stops sleeping */
EVT_SLEEPING,
/** Actor is in rooted state (cannot move) */
EVT_ROOTED,
/**
* An event that previous action was completed. The action may be an attempt to physically/magically hit an enemy, or an action that discarded attack attempt has finished.
*/
EVT_READY_TO_ACT,
/**
* User's command, like using a combat magic or changing weapon, etc. The command is not intended to change final goal
*/
EVT_USER_CMD,
/**
* The actor arrived to assigned location, or it's a time to modify movement destination (follow, interact, random move and others intentions).
*/
EVT_ARRIVED,
/**
* The actor arrived to an intermidiate point, and needs revalidate destination. This is sent when follow/move to pawn if destination is far away.
*/
EVT_ARRIVED_REVALIDATE,
/** The actor cannot move anymore. */
EVT_ARRIVED_BLOCKED,
/** Forgets an object (if it's used as attack target, follow target and so on */
EVT_FORGET_OBJECT,
/**
* Attempt to cancel current step execution, but not change the intention. For example, the actor was putted into a stun, so it's current attack or movement has to be canceled. But after the stun state expired, the actor may try to attack again. Another usage for CANCEL is a user's attempt to
* cancel a cast/bow attack and so on.
*/
EVT_CANCEL,
/** The character is dead */
EVT_DEAD,
/** The character looks like dead */
EVT_FAKE_DEATH,
/** The character attack anyone randomly **/
EVT_CONFUSED,
/** The character cannot cast spells anymore **/
EVT_MUTED,
/** The character flee in randoms directions **/
EVT_AFRAID,
/** The character finish casting **/
EVT_FINISH_CASTING
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
/**
* Enumaration of generic intentions of an NPC/PC, an intention may require several steps to be completed
*/
public enum CtrlIntention
{
/** Do nothing, disconnect AI of NPC if no players around */
AI_INTENTION_IDLE,
/** Alerted state without goal : scan attackable targets, random walk, etc */
AI_INTENTION_ACTIVE,
/** Rest (sit until attacked) */
AI_INTENTION_REST,
/**
* Attack target (cast combat magic, go to target, combat), may be ignored, if target is locked on another character or a peacefull zone and so on
*/
AI_INTENTION_ATTACK,
/** Cast a spell, depending on the spell - may start or stop attacking */
AI_INTENTION_CAST,
/** Just move to another location */
AI_INTENTION_MOVE_TO,
/** Like move, but check target's movement and follow it */
AI_INTENTION_FOLLOW,
/** PickUp and item, (got to item, pickup it, become idle */
AI_INTENTION_PICK_UP,
/** Move to target, then interact */
AI_INTENTION_INTERACT;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,168 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import com.l2jmobius.gameserver.model.L2CharPosition;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.actor.instance.L2BoatInstance;
import com.l2jmobius.gameserver.network.serverpackets.VehicleDeparture;
import com.l2jmobius.gameserver.network.serverpackets.VehicleInfo;
import com.l2jmobius.gameserver.network.serverpackets.VehicleStarted;
/**
* @author DS
*/
public class L2BoatAI extends L2CharacterAI
{
public L2BoatAI(L2BoatInstance.AIAccessor accessor)
{
super(accessor);
}
@Override
protected void onIntentionAttack(L2Character target)
{
}
@Override
protected void onIntentionCast(L2Skill skill, L2Object target)
{
}
@Override
protected void onIntentionFollow(L2Character target)
{
}
@Override
protected void onIntentionPickUp(L2Object item)
{
}
@Override
protected void onIntentionInteract(L2Object object)
{
}
@Override
protected void onEvtAttacked(L2Character attacker)
{
}
@Override
protected void onEvtAggression(L2Character target, int aggro)
{
}
@Override
protected void onEvtStunned(L2Character attacker)
{
}
@Override
protected void onEvtSleeping(L2Character attacker)
{
}
@Override
protected void onEvtRooted(L2Character attacker)
{
}
@Override
protected void onEvtForgetObject(L2Object object)
{
}
@Override
protected void onEvtCancel()
{
}
@Override
protected void onEvtDead()
{
}
@Override
protected void onEvtFakeDeath()
{
}
@Override
protected void onEvtFinishCasting()
{
}
@Override
protected void clientActionFailed()
{
}
@Override
protected void moveToPawn(L2Object pawn, int offset)
{
}
@Override
protected void moveTo(int x, int y, int z)
{
if (!_actor.isMovementDisabled())
{
if (!_client_moving)
{
_actor.broadcastPacket(new VehicleStarted(_actor.getObjectId(), 1));
}
_client_moving = true;
_accessor.moveTo(x, y, z);
_actor.broadcastPacket(new VehicleDeparture(getActor()));
}
}
@Override
protected void clientStoppedMoving()
{
_client_moving = false;
_actor.broadcastPacket(new VehicleStarted(_actor.getObjectId(), 0));
_actor.broadcastPacket(new VehicleInfo(getActor()));
}
@Override
protected void clientStopMoving(L2CharPosition pos)
{
if (_actor.isMoving())
{
_accessor.stopMove(pos);
}
if (_client_moving || (pos != null))
{
_client_moving = false;
_actor.broadcastPacket(new VehicleStarted(_actor.getObjectId(), 0));
_actor.broadcastPacket(new VehicleInfo(getActor()));
}
}
@Override
public L2BoatInstance getActor()
{
return (L2BoatInstance) _actor;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,643 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import java.util.List;
import com.l2jmobius.gameserver.model.L2Attackable;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Character.AIAccessor;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.MobGroup;
import com.l2jmobius.gameserver.model.MobGroupTable;
import com.l2jmobius.gameserver.model.actor.instance.L2ControllableMobInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2FolkInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PlayableInstance;
import com.l2jmobius.gameserver.util.Util;
import com.l2jmobius.util.Rnd;
import javolution.util.FastList;
/**
* @author littlecrow AI for controllable mobs
*/
public class L2ControllableMobAI extends L2AttackableAI
{
public static final int AI_IDLE = 1;
public static final int AI_NORMAL = 2;
public static final int AI_FORCEATTACK = 3;
public static final int AI_FOLLOW = 4;
public static final int AI_CAST = 5;
public static final int AI_ATTACK_GROUP = 6;
private int _alternateAI;
private boolean _isThinking; // to prevent thinking recursively
private boolean _isNotMoving;
private L2Character _forcedTarget;
private MobGroup _targetGroup;
protected void thinkFollow()
{
final L2Attackable me = (L2Attackable) _actor;
if (!Util.checkIfInRange(MobGroupTable.FOLLOW_RANGE, me, getForcedTarget(), true))
{
final int signX = (Rnd.nextInt(2) == 0) ? -1 : 1;
final int signY = (Rnd.nextInt(2) == 0) ? -1 : 1;
final int randX = Rnd.nextInt(MobGroupTable.FOLLOW_RANGE);
final int randY = Rnd.nextInt(MobGroupTable.FOLLOW_RANGE);
moveTo(getForcedTarget().getX() + (signX * randX), getForcedTarget().getY() + (signY * randY), getForcedTarget().getZ());
}
}
@Override
protected void onEvtThink()
{
if (isThinking() || _actor.isAllSkillsDisabled())
{
return;
}
setThinking(true);
try
{
switch (getAlternateAI())
{
case AI_IDLE:
if (getIntention() != CtrlIntention.AI_INTENTION_ACTIVE)
{
setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
break;
case AI_FOLLOW:
thinkFollow();
break;
case AI_CAST:
thinkCast();
break;
case AI_FORCEATTACK:
thinkForceAttack();
break;
case AI_ATTACK_GROUP:
thinkAttackGroup();
break;
default:
if (getIntention() == AI_INTENTION_ACTIVE)
{
thinkActive();
}
else if (getIntention() == AI_INTENTION_ATTACK)
{
thinkAttack();
}
break;
}
}
finally
{
setThinking(false);
}
}
protected void thinkCast()
{
final L2Attackable npc = (L2Attackable) _actor;
if ((getAttackTarget() == null) || getAttackTarget().isAlikeDead())
{
setAttackTarget(findNextRndTarget());
clientStopMoving(null);
}
if (getAttackTarget() == null)
{
return;
}
npc.setTarget(getAttackTarget());
L2Skill[] skills = null;
try
{
skills = _actor.getAllSkills();
}
catch (final NullPointerException e)
{
_log.warning("Encountered Null Value.");
e.printStackTrace();
}
if (!_actor.isMuted())
{
int max_range = 0;
// check distant skills
if (skills != null)
{
for (final L2Skill sk : skills)
{
if (Util.checkIfInRange(sk.getCastRange(), _actor, getAttackTarget(), true) && !_actor.isSkillDisabled(sk.getId()) && (_actor.getCurrentMp() > _actor.getStat().getMpConsume(sk)))
{
_accessor.doCast(sk);
return;
}
max_range = Math.max(max_range, sk.getCastRange());
}
}
if (!isNotMoving())
{
moveToPawn(getAttackTarget(), max_range);
}
return;
}
}
protected void thinkAttackGroup()
{
final L2Character target = getForcedTarget();
if ((target == null) || target.isAlikeDead())
{
// try to get next group target
setForcedTarget(findNextGroupTarget());
clientStopMoving(null);
}
if (target == null)
{
return;
}
L2Skill[] skills = null;
double dist2 = 0;
int range = 0;
int max_range = 0;
_actor.setTarget(target);
// as a response, we put the target in a forcedattack mode
final L2ControllableMobInstance theTarget = (L2ControllableMobInstance) target;
final L2ControllableMobAI ctrlAi = (L2ControllableMobAI) theTarget.getAI();
ctrlAi.forceAttack(_actor);
try
{
skills = _actor.getAllSkills();
dist2 = _actor.getPlanDistanceSq(target.getX(), target.getY());
range = _actor.getPhysicalAttackRange() + (int) (_actor.getTemplate().collisionRadius + target.getTemplate().collisionRadius);
max_range = range;
}
catch (final NullPointerException e)
{
_log.warning("Encountered Null Value.");
e.printStackTrace();
}
if (!_actor.isMuted() && (dist2 > ((range + 20) * (range + 20))))
{
// check distant skills
if (skills != null)
{
for (final L2Skill sk : skills)
{
final int castRange = sk.getCastRange();
if (((castRange * castRange) >= dist2) && !_actor.isSkillDisabled(sk.getId()) && (_actor.getCurrentMp() > _actor.getStat().getMpConsume(sk)))
{
_accessor.doCast(sk);
return;
}
max_range = Math.max(max_range, castRange);
}
}
if (!isNotMoving())
{
moveToPawn(target, range);
}
return;
}
_accessor.doAttack(target);
}
protected void thinkForceAttack()
{
if ((getForcedTarget() == null) || getForcedTarget().isAlikeDead())
{
clientStopMoving(null);
setIntention(AI_INTENTION_ACTIVE);
setAlternateAI(AI_IDLE);
}
L2Skill[] skills = null;
double dist2 = 0;
int range = 0;
int max_range = 0;
try
{
_actor.setTarget(getForcedTarget());
skills = _actor.getAllSkills();
dist2 = _actor.getPlanDistanceSq(getForcedTarget().getX(), getForcedTarget().getY());
range = _actor.getPhysicalAttackRange() + (int) (_actor.getTemplate().collisionRadius + getForcedTarget().getTemplate().collisionRadius);
max_range = range;
}
catch (final NullPointerException e)
{
_log.warning("Encountered Null Value.");
e.printStackTrace();
}
if (!_actor.isMuted() && (dist2 > ((range + 20) * (range + 20))))
{
// check distant skills
if (skills != null)
{
for (final L2Skill sk : skills)
{
final int castRange = sk.getCastRange();
if (((castRange * castRange) >= dist2) && !_actor.isSkillDisabled(sk.getId()) && (_actor.getCurrentMp() > _actor.getStat().getMpConsume(sk)))
{
_accessor.doCast(sk);
return;
}
max_range = Math.max(max_range, castRange);
}
}
if (!isNotMoving())
{
moveToPawn(getForcedTarget(), _actor.getPhysicalAttackRange());
}
return;
}
_accessor.doAttack(getForcedTarget());
}
protected void thinkAttack()
{
if ((getAttackTarget() == null) || getAttackTarget().isAlikeDead())
{
if (getAttackTarget() != null)
{
// stop hating
final L2Attackable npc = (L2Attackable) _actor;
npc.stopHating(getAttackTarget());
}
setIntention(AI_INTENTION_ACTIVE);
}
else
{
// notify aggression
if ((((L2NpcInstance) _actor).getFactionId() != null) && !(getAttackTarget() instanceof L2Attackable))
{
final String faction_id = ((L2NpcInstance) _actor).getFactionId();
for (final L2Object obj : _actor.getKnownList().getKnownObjects().values())
{
if (!(obj instanceof L2NpcInstance))
{
continue;
}
final L2NpcInstance npc = (L2NpcInstance) obj;
if (!faction_id.equals(npc.getFactionId()))
{
continue;
}
if (_actor.isInsideRadius(npc, (npc.getFactionRange() + npc.getAggroRange()), false, true) && (Math.abs(getAttackTarget().getZ() - npc.getZ()) < 600) && _actor.getAttackByList().contains(getAttackTarget()) && (npc.getAI() != null) && (npc.getAI()._intention != CtrlIntention.AI_INTENTION_ATTACK))
{
npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, getAttackTarget(), 1);
}
}
}
L2Skill[] skills = null;
double dist2 = 0;
int range = 0;
int max_range = 0;
try
{
_actor.setTarget(getAttackTarget());
skills = _actor.getAllSkills();
dist2 = _actor.getPlanDistanceSq(getAttackTarget().getX(), getAttackTarget().getY());
range = _actor.getPhysicalAttackRange() + (int) (_actor.getTemplate().collisionRadius + getAttackTarget().getTemplate().collisionRadius);
max_range = range;
}
catch (final NullPointerException e)
{
_log.warning("Encountered Null Value.");
e.printStackTrace();
}
if (!_actor.isMuted() && (dist2 > ((range + 20) * (range + 20))))
{
// check distant skills
if (skills != null)
{
for (final L2Skill sk : skills)
{
final int castRange = sk.getCastRange();
if (((castRange * castRange) >= dist2) && !_actor.isSkillDisabled(sk.getId()) && (_actor.getCurrentMp() > _actor.getStat().getMpConsume(sk)))
{
_accessor.doCast(sk);
return;
}
max_range = Math.max(max_range, castRange);
}
}
moveToPawn(getAttackTarget(), range);
return;
}
// Force mobs to attack anybody if confused.
L2Character hated;
if (_actor.isConfused())
{
hated = findNextRndTarget();
}
else
{
hated = getAttackTarget();
}
if (hated == null)
{
setIntention(AI_INTENTION_ACTIVE);
return;
}
if (hated != getAttackTarget())
{
setAttackTarget(hated);
}
if (!_actor.isMuted() && (skills != null) && (skills.length > 0) && (Rnd.nextInt(5) == 3))
{
for (final L2Skill sk : skills)
{
final int castRange = sk.getCastRange();
if (((castRange * castRange) >= dist2) && !_actor.isSkillDisabled(sk.getId()) && (_actor.getCurrentMp() < _actor.getStat().getMpConsume(sk)))
{
_accessor.doCast(sk);
return;
}
}
}
_accessor.doAttack(getAttackTarget());
}
}
private void thinkActive()
{
setAttackTarget(findNextRndTarget());
L2Character hated;
if (_actor.isConfused())
{
hated = findNextRndTarget();
}
else
{
hated = getAttackTarget();
}
if (hated != null)
{
_actor.setRunning();
setIntention(CtrlIntention.AI_INTENTION_ATTACK, hated);
}
}
private boolean autoAttackCondition(L2Character target)
{
if ((target == null) || !(_actor instanceof L2Attackable))
{
return false;
}
final L2Attackable me = (L2Attackable) _actor;
if ((target instanceof L2FolkInstance) || (target instanceof L2DoorInstance))
{
return false;
}
if (target.isAlikeDead() || !me.isInsideRadius(target, me.getAggroRange(), false, false) || (Math.abs(_actor.getZ() - target.getZ()) > 100))
{
return false;
}
// Check if the target isn't invulnerable
if (target.isInvul())
{
return false;
}
// Check if the target is a L2PlayableInstance
if (target instanceof L2PlayableInstance)
{
// Check if the target isn't in silent move mode
if (((L2PlayableInstance) target).isSilentMoving())
{
return false;
}
}
if (target instanceof L2NpcInstance)
{
return false;
}
return me.isAggressive();
}
private L2Character findNextRndTarget()
{
if (getAttackTarget() == null)
{
return null;
}
final int aggroRange = ((L2Attackable) _actor).getAggroRange();
final L2Attackable npc = (L2Attackable) _actor;
int npcX, npcY, targetX, targetY;
double dy, dx;
final double dblAggroRange = aggroRange * aggroRange;
final List<L2Character> potentialTarget = new FastList<>();
for (final L2Object obj : npc.getKnownList().getKnownObjects().values())
{
if (!(obj instanceof L2Character))
{
continue;
}
npcX = npc.getX();
npcY = npc.getY();
targetX = obj.getX();
targetY = obj.getY();
dx = npcX - targetX;
dy = npcY - targetY;
if (((dx * dx) + (dy * dy)) > dblAggroRange)
{
continue;
}
final L2Character target = (L2Character) obj;
if (autoAttackCondition(target))
{
potentialTarget.add(target);
}
}
if (potentialTarget.size() == 0)
{
return null;
}
// we choose a random target
final int choice = Rnd.nextInt(potentialTarget.size());
final L2Character target = potentialTarget.get(choice);
return target;
}
private L2ControllableMobInstance findNextGroupTarget()
{
return getGroupTarget().getRandomMob();
}
public L2ControllableMobAI(AIAccessor accessor)
{
super(accessor);
setAlternateAI(AI_IDLE);
}
public int getAlternateAI()
{
return _alternateAI;
}
public void setAlternateAI(int _alternateai)
{
_alternateAI = _alternateai;
}
public void forceAttack(L2Character target)
{
setAlternateAI(AI_FORCEATTACK);
setForcedTarget(target);
}
public void forceAttackGroup(MobGroup group)
{
setForcedTarget(null);
setGroupTarget(group);
setAlternateAI(AI_ATTACK_GROUP);
}
public void stop()
{
setAlternateAI(AI_IDLE);
clientStopMoving(null);
}
public void move(int x, int y, int z)
{
moveTo(x, y, z);
}
public void follow(L2Character target)
{
setAlternateAI(AI_FOLLOW);
setForcedTarget(target);
}
public boolean isThinking()
{
return _isThinking;
}
public boolean isNotMoving()
{
return _isNotMoving;
}
public void setNotMoving(boolean isNotMoving)
{
_isNotMoving = isNotMoving;
}
public void setThinking(boolean isThinking)
{
_isThinking = isThinking;
}
private L2Character getForcedTarget()
{
return _forcedTarget;
}
private MobGroup getGroupTarget()
{
return _targetGroup;
}
private void setForcedTarget(L2Character forcedTarget)
{
_forcedTarget = forcedTarget;
}
private void setGroupTarget(MobGroup targetGroup)
{
_targetGroup = targetGroup;
}
}

View File

@@ -0,0 +1,178 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.L2CharPosition;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2SiegeGuardInstance;
/**
* @author mkizub TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
*/
public class L2DoorAI extends L2CharacterAI
{
public L2DoorAI(L2DoorInstance.AIAccessor accessor)
{
super(accessor);
}
// rather stupid AI... well, it's for doors :D
@Override
protected void onIntentionIdle()
{
}
@Override
protected void onIntentionActive()
{
}
@Override
protected void onIntentionRest()
{
}
@Override
protected void onIntentionAttack(L2Character target)
{
}
@Override
protected void onIntentionCast(L2Skill skill, L2Object target)
{
}
@Override
protected void onIntentionMoveTo(L2CharPosition destination)
{
}
@Override
protected void onIntentionFollow(L2Character target)
{
}
@Override
protected void onIntentionPickUp(L2Object item)
{
}
@Override
protected void onIntentionInteract(L2Object object)
{
}
@Override
protected void onEvtThink()
{
}
@Override
protected void onEvtAttacked(L2Character attacker)
{
final L2DoorInstance me = (L2DoorInstance) _actor;
ThreadPoolManager.getInstance().executeTask(new onEventAttackedDoorTask(me, attacker));
}
@Override
protected void onEvtAggression(L2Character target, int aggro)
{
}
@Override
protected void onEvtStunned(L2Character attacker)
{
}
@Override
protected void onEvtSleeping(L2Character attacker)
{
}
@Override
protected void onEvtRooted(L2Character attacker)
{
}
@Override
protected void onEvtReadyToAct()
{
}
@Override
protected void onEvtUserCmd(Object arg0, Object arg1)
{
}
@Override
protected void onEvtArrived()
{
}
@Override
protected void onEvtArrivedRevalidate()
{
}
@Override
protected void onEvtArrivedBlocked(L2CharPosition blocked_at_pos)
{
}
@Override
protected void onEvtForgetObject(L2Object object)
{
}
@Override
protected void onEvtCancel()
{
}
@Override
protected void onEvtDead()
{
}
private class onEventAttackedDoorTask implements Runnable
{
private final L2DoorInstance _door;
private final L2Character _attacker;
public onEventAttackedDoorTask(L2DoorInstance door, L2Character attacker)
{
_door = door;
_attacker = attacker;
}
@Override
public void run()
{
for (final L2SiegeGuardInstance guard : _door.getKnownSiegeGuards())
{
if (_actor.isInsideRadius(guard, guard.getFactionRange(), false, true) && (Math.abs(_attacker.getZ() - guard.getZ()) < 200))
{
guard.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, _attacker, 15);
}
}
}
}
}

View File

@@ -0,0 +1,240 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.datatables.NpcWalkerRoutesTable;
import com.l2jmobius.gameserver.model.L2CharPosition;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2NpcWalkerNode;
import com.l2jmobius.gameserver.model.actor.instance.L2NpcWalkerInstance;
import javolution.util.FastList;
public class L2NpcWalkerAI extends L2CharacterAI implements Runnable
{
protected static final Logger _log = Logger.getLogger(L2NpcWalkerAI.class.getName());
private static final int DEFAULT_MOVE_DELAY = 0;
private long _nextMoveTime;
private boolean _walkingToNextPoint = false;
/**
* home points for xyz
*/
int _homeX, _homeY, _homeZ;
/**
* route of the current npc
*/
private FastList<L2NpcWalkerNode> _route;
/**
* current node
*/
private int _currentPos;
/**
* Constructor of L2CharacterAI.<BR>
* <BR>
* @param accessor The AI accessor of the L2Character
*/
public L2NpcWalkerAI(L2Character.AIAccessor accessor)
{
super(accessor);
if (!Config.ALLOW_NPC_WALKERS)
{
return;
}
_route = NpcWalkerRoutesTable.getInstance().getRouteForNpc(getActor().getNpcId());
// Here we need 1 second initial delay cause getActor().hasAI() will return null...
// Constructor of L2NpcWalkerAI is called faster then ai object is attached in L2NpcWalkerInstance
ThreadPoolManager.getInstance().scheduleAiAtFixedRate(this, 1000, 1000);
}
@Override
public void run()
{
onEvtThink();
}
@Override
protected void onEvtThink()
{
if (!Config.ALLOW_NPC_WALKERS)
{
return;
}
if (isWalkingToNextPoint())
{
checkArrived();
return;
}
if (_nextMoveTime < System.currentTimeMillis())
{
walkToLocation();
}
}
/**
* If npc can't walk to it's target then just teleport to next point
* @param blocked_at_pos ignoring it
*/
@Override
protected void onEvtArrivedBlocked(L2CharPosition blocked_at_pos)
{
_log.warning("NpcWalker ID: " + getActor().getNpcId() + ": Blocked at rote position [" + _currentPos + "], coords: " + blocked_at_pos.x + ", " + blocked_at_pos.y + ", " + blocked_at_pos.z + ". Teleporting to next point");
final int destinationX = _route.get(_currentPos).getMoveX();
final int destinationY = _route.get(_currentPos).getMoveY();
final int destinationZ = _route.get(_currentPos).getMoveZ();
getActor().teleToLocation(destinationX, destinationY, destinationZ, false);
super.onEvtArrivedBlocked(blocked_at_pos);
}
private void checkArrived()
{
final int destinationX = _route.get(_currentPos).getMoveX();
final int destinationY = _route.get(_currentPos).getMoveY();
final int destinationZ = _route.get(_currentPos).getMoveZ();
if ((getActor().getX() == destinationX) && (getActor().getY() == destinationY) && (getActor().getZ() == destinationZ))
{
final String chat = _route.get(_currentPos).getChatText();
if ((chat != null) && !chat.isEmpty())
{
try
{
getActor().broadcastChat(chat);
}
catch (final ArrayIndexOutOfBoundsException e)
{
_log.info("L2NpcWalkerInstance: Error, " + e);
}
}
// time in millis
long delay = _route.get(_currentPos).getDelay() * 1000;
// sleeps between each move
if ((delay <= 0) && (delay != DEFAULT_MOVE_DELAY))
{
delay = DEFAULT_MOVE_DELAY;
if (Config.DEVELOPER)
{
_log.warning("Wrong Delay Set in Npc Walker Functions = " + delay + " secs, using default delay: " + DEFAULT_MOVE_DELAY + " secs instead.");
}
}
_nextMoveTime = System.currentTimeMillis() + delay;
setWalkingToNextPoint(false);
}
}
private void walkToLocation()
{
if (_currentPos < (_route.size() - 1))
{
_currentPos++;
}
else
{
_currentPos = 0;
}
final boolean moveType = _route.get(_currentPos).getRunning();
/**
* false - walking true - Running
*/
if (moveType)
{
getActor().setRunning();
}
else
{
getActor().setWalking();
}
// now we define destination
final int destinationX = _route.get(_currentPos).getMoveX();
final int destinationY = _route.get(_currentPos).getMoveY();
final int destinationZ = _route.get(_currentPos).getMoveZ();
// notify AI of MOVE_TO
setWalkingToNextPoint(true);
setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(destinationX, destinationY, destinationZ, 0));
}
@Override
public L2NpcWalkerInstance getActor()
{
return (L2NpcWalkerInstance) super.getActor();
}
public int getHomeX()
{
return _homeX;
}
public int getHomeY()
{
return _homeY;
}
public int getHomeZ()
{
return _homeZ;
}
public void setHomeX(int homeX)
{
_homeX = homeX;
}
public void setHomeY(int homeY)
{
_homeY = homeY;
}
public void setHomeZ(int homeZ)
{
_homeZ = homeZ;
}
public boolean isWalkingToNextPoint()
{
return _walkingToNextPoint;
}
public void setWalkingToNextPoint(boolean value)
{
_walkingToNextPoint = value;
}
}

View File

@@ -0,0 +1,392 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_MOVE_TO;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import com.l2jmobius.gameserver.model.L2CharPosition;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Character.AIAccessor;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2StaticObjectInstance;
public class L2PlayerAI extends L2CharacterAI
{
private boolean thinking; // to prevent recursive thinking
public L2PlayerAI(AIAccessor accessor)
{
super(accessor);
}
/**
* Saves the current Intention for this L2PlayerAI if necessary and calls changeIntention in AbstractAI.<BR>
* <BR>
* @param intention The new Intention to set to the AI
* @param arg0 The first parameter of the Intention
* @param arg1 The second parameter of the Intention
*/
@Override
public synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
{
// do nothing unless CAST intention
// however, forget interrupted actions when starting to use an offensive skill
if ((intention != AI_INTENTION_CAST) || ((arg0 != null) && ((L2Skill) arg0).isOffensive()))
{
boolean hasStandIntention = false;
if ((_actor instanceof L2PcInstance) && ((L2PcInstance) _actor).isSitting())
{
hasStandIntention = true;
}
if (!hasStandIntention)
{
_nextIntention = null;
}
super.changeIntention(intention, arg0, arg1);
return;
}
// do nothing if next intention is same as current one.
if ((intention == _intention) && (arg0 == _intention_arg0) && (arg1 == _intention_arg1))
{
super.changeIntention(intention, arg0, arg1);
return;
}
// save current intention so it can be used after cast
saveNextIntention(_intention, _intention_arg0, _intention_arg1);
super.changeIntention(intention, arg0, arg1);
}
/**
* Launch actions corresponding to the Event ReadyToAct.<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Launch actions corresponding to the Event Think</li><BR>
* <BR>
*/
@Override
protected void onEvtReadyToAct()
{
// Launch actions corresponding to the Event Think
if (_nextIntention != null)
{
setIntention(_nextIntention._crtlIntention, _nextIntention._arg0, _nextIntention._arg1);
_nextIntention = null;
}
super.onEvtReadyToAct();
}
/**
* Launch actions corresponding to the Event Cancel.<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Stop an AI Follow Task</li>
* <li>Launch actions corresponding to the Event Think</li><BR>
* <BR>
*/
@Override
protected void onEvtCancel()
{
_nextIntention = null;
super.onEvtCancel();
}
/**
* Finalize the casting of a skill. This method overrides L2CharacterAI method.<BR>
* <BR>
* <B>What it does:</B> Check if actual intention is set to CAST and, if so, retrieves latest intention before the actual CAST and set it as the current intention for the player
*/
@Override
protected void onEvtFinishCasting()
{
if (getIntention() == AI_INTENTION_CAST)
{
// run interrupted or next intention
final IntentionCommand nextIntention = _nextIntention;
if (nextIntention != null)
{
if (nextIntention._crtlIntention != AI_INTENTION_CAST)
{
setIntention(nextIntention._crtlIntention, nextIntention._arg0, nextIntention._arg1);
}
else
{
setIntention(AI_INTENTION_IDLE);
}
}
else
{
// set intention to idle if skill doesn't change intention.
setIntention(AI_INTENTION_IDLE);
}
}
}
@Override
protected void onIntentionRest()
{
if (getIntention() != AI_INTENTION_REST)
{
changeIntention(AI_INTENTION_REST, null, null);
setTarget(null);
if (getAttackTarget() != null)
{
setAttackTarget(null);
}
clientStopMoving(null);
}
}
@Override
protected void onIntentionActive()
{
setIntention(AI_INTENTION_IDLE);
}
/**
* Manage the Move To Intention : Stop current Attack and Launch a Move to Location Task.<BR>
* <BR>
* <B><U> Actions</U> : </B><BR>
* <BR>
* <li>Stop the actor auto-attack server side AND client side by sending Server->Client packet AutoAttackStop (broadcast)</li>
* <li>Set the Intention of this AI to AI_INTENTION_MOVE_TO</li>
* <li>Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)</li><BR>
* <BR>
*/
@Override
protected void onIntentionMoveTo(L2CharPosition pos)
{
if (getIntention() == AI_INTENTION_REST)
{
// Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor
clientActionFailed();
saveNextIntention(AI_INTENTION_MOVE_TO, pos, null);
return;
}
if (_actor.isAllSkillsDisabled() || (_actor.isAttackingNow() && !_actor.isAfraid()))
{
clientActionFailed();
saveNextIntention(AI_INTENTION_MOVE_TO, pos, null);
return;
}
// Set the Intention of this AbstractAI to AI_INTENTION_MOVE_TO
changeIntention(AI_INTENTION_MOVE_TO, pos, null);
// Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop (broadcast)
clientStopAutoAttack();
// Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
moveTo(pos.x, pos.y, pos.z);
}
@Override
protected void clientNotifyDead()
{
_client_moving_to_pawn_offset = 0;
_client_moving = false;
super.clientNotifyDead();
}
private void thinkAttack()
{
final L2Character target = getAttackTarget();
if (target == null)
{
return;
}
if (checkTargetLostOrDead(target))
{
// if (target != null)
// {
// Notify the target
setAttackTarget(null);
// }
return;
}
if (maybeMoveToPawn(target, _actor.getPhysicalAttackRange()))
{
return;
}
_accessor.doAttack(target);
}
private void thinkCast()
{
final L2Character target = getCastTarget();
if (checkTargetLost(target))
{
if (_skill.isOffensive() && (getAttackTarget() != null))
{
// Notify the target
setCastTarget(null);
}
return;
}
if (target != null)
{
if (maybeMoveToPawn(target, _actor.getMagicalAttackRange(_skill)))
{
return;
}
}
if (_skill.getHitTime() > 50)
{
clientStopMoving(null);
}
final L2Object oldTarget = _actor.getTarget();
if (oldTarget != null)
{
// Replace the current target by the cast target
if ((target != null) && (oldTarget != target))
{
_actor.setTarget(getCastTarget());
}
// Launch the Cast of the skill
_accessor.doCast(_skill);
// Restore the initial target
if ((target != null) && (oldTarget != target))
{
_actor.setTarget(oldTarget);
}
}
else
{
_accessor.doCast(_skill);
}
}
private void thinkPickUp()
{
if (_actor.isAllSkillsDisabled())
{
return;
}
final L2Object target = getTarget();
if (target == null)
{
return;
}
if (checkTargetLost(target))
{
return;
}
if (maybeMoveToPawn(target, 36))
{
return;
}
setIntention(AI_INTENTION_IDLE);
((L2PcInstance.AIAccessor) _accessor).doPickupItem(target);
}
private void thinkInteract()
{
if (_actor.isAllSkillsDisabled())
{
return;
}
final L2Object target = getTarget();
if (target == null)
{
return;
}
if (checkTargetLost(target))
{
return;
}
if (maybeMoveToPawn(target, 36))
{
return;
}
if (!(target instanceof L2StaticObjectInstance))
{
((L2PcInstance.AIAccessor) _accessor).doInteract((L2Character) target);
}
setIntention(AI_INTENTION_IDLE);
}
@Override
protected void onEvtThink()
{
if (thinking || _actor.isAllSkillsDisabled())
{
return;
}
thinking = true;
try
{
if (getIntention() == AI_INTENTION_ATTACK)
{
thinkAttack();
}
else if (getIntention() == AI_INTENTION_CAST)
{
thinkCast();
}
else if (getIntention() == AI_INTENTION_PICK_UP)
{
thinkPickUp();
}
else if (getIntention() == AI_INTENTION_INTERACT)
{
thinkInteract();
}
}
finally
{
thinking = false;
}
}
@Override
protected void onEvtArrivedRevalidate()
{
super.onEvtArrivedRevalidate();
}
}

View File

@@ -0,0 +1,957 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
import java.util.concurrent.Future;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.GameTimeController;
import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.L2Attackable;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Effect;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2FolkInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PlayableInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2SiegeGuardInstance;
import com.l2jmobius.gameserver.util.Util;
import com.l2jmobius.util.Rnd;
/**
* This class manages AI of L2Attackable.<BR>
* <BR>
*/
public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
{
// protected static final Logger _log = Logger.getLogger(L2SiegeGuardAI.class.getName());
private static final int MAX_ATTACK_TIMEOUT = 300; // int ticks, i.e. 30 seconds
/** The L2Attackable AI task executed every 1s (call onEvtThink method) */
private Future<?> aiTask;
/** For attack AI, analysis of mob and its targets */
private final SelfAnalysis _selfAnalysis = new SelfAnalysis();
/** The delay after which the attack is stopped */
private int _attackTimeout;
/** The L2Attackable aggro counter */
private int _globalAggro;
/** The flag used to indicate that a thinking action is in progress */
private boolean thinking; // to prevent recursive thinking
private final int attackRange;
/**
* Constructor of L2AttackableAI.<BR>
* <BR>
* @param accessor The AI accessor of the L2Character
*/
public L2SiegeGuardAI(L2Character.AIAccessor accessor)
{
super(accessor);
_selfAnalysis.Init();
_attackTimeout = Integer.MAX_VALUE;
_globalAggro = -10; // 10 seconds timeout of ATTACK after respawn
attackRange = ((L2Attackable) _actor).getPhysicalAttackRange();
}
@Override
public void run()
{
// Launch actions corresponding to the Event Think
onEvtThink();
}
/**
* Return True if the target is autoattackable (depends on the actor type).<BR>
* <BR>
* <B><U> Actor is a L2GuardInstance</U> :</B><BR>
* <BR>
* <li>The target isn't a Folk or a Door</li>
* <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
* <li>The target is in the actor Aggro range and is at the same height</li>
* <li>The L2PcInstance target has karma (=PK)</li>
* <li>The L2MonsterInstance target is aggressive</li><BR>
* <BR>
* <B><U> Actor is a L2SiegeGuardInstance</U> :</B><BR>
* <BR>
* <li>The target isn't a Folk or a Door</li>
* <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
* <li>The target is in the actor Aggro range and is at the same height</li>
* <li>A siege is in progress</li>
* <li>The L2PcInstance target isn't a Defender</li><BR>
* <BR>
* <B><U> Actor is a L2FriendlyMobInstance</U> :</B><BR>
* <BR>
* <li>The target isn't a Folk, a Door or another L2NpcInstance</li>
* <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
* <li>The target is in the actor Aggro range and is at the same height</li>
* <li>The L2PcInstance target has karma (=PK)</li><BR>
* <BR>
* <B><U> Actor is a L2MonsterInstance</U> :</B><BR>
* <BR>
* <li>The target isn't a Folk, a Door or another L2NpcInstance</li>
* <li>The target isn't dead, isn't invulnerable, isn't in silent moving mode AND too far (>100)</li>
* <li>The target is in the actor Aggro range and is at the same height</li>
* <li>The actor is Aggressive</li><BR>
* <BR>
* @param target The targeted L2Object
* @return
*/
private boolean autoAttackCondition(L2Character target)
{
// Check if the target isn't another guard, folk or a door
if ((target == null) || (target instanceof L2SiegeGuardInstance) || (target instanceof L2FolkInstance) || (target instanceof L2DoorInstance))
{
return false;
}
// Check if the target isn't dead
if (target.isAlikeDead())
{
return false;
}
// Check if the target isn't invulnerable
if (target.isInvul())
{
if ((target.getActingPlayer() != null) && target.getActingPlayer().isGM())
{
return false;
}
}
// Get the owner if the target is a summon
if (target instanceof L2Summon)
{
final L2PcInstance owner = ((L2Summon) target).getOwner();
if (_actor.isInsideRadius(owner, 1000, true, false))
{
target = owner;
}
}
// Check if the target is a L2PcInstance
if (target instanceof L2PlayableInstance)
{
// Check if the target isn't in silent move mode AND too far (>250)
if (((L2PlayableInstance) target).isSilentMoving() && !_actor.isInsideRadius(target, 250, false, false))
{
return false;
}
}
// Los Check Here
return (_actor.isAutoAttackable(target) && GeoData.getInstance().canSeeTarget(_actor, target));
}
/**
* Set the Intention of this L2CharacterAI and create an AI Task executed every 1s (call onEvtThink method) for this L2Attackable.<BR>
* <BR>
* <FONT COLOR=#FF0000><B> <U>Caution</U> : If actor _knowPlayer isn't EMPTY, AI_INTENTION_IDLE will be change in AI_INTENTION_ACTIVE</B></FONT><BR>
* <BR>
* @param intention The new Intention to set to the AI
* @param arg0 The first parameter of the Intention
* @param arg1 The second parameter of the Intention
*/
@Override
synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
{
if (Config.DEBUG)
{
_log.info("L2SiegeAI.changeIntention(" + intention + ", " + arg0 + ", " + arg1 + ")");
}
if (intention == AI_INTENTION_IDLE /* || intention == AI_INTENTION_ACTIVE */) // active becomes idle if only a summon is present
{
// Check if actor is not dead
if (!_actor.isAlikeDead())
{
final L2Attackable npc = (L2Attackable) _actor;
// If its _knownPlayer isn't empty set the Intention to AI_INTENTION_ACTIVE
if (npc.getKnownList().getKnownPlayers().size() > 0)
{
intention = AI_INTENTION_ACTIVE;
}
else
{
intention = AI_INTENTION_IDLE;
}
}
if (intention == AI_INTENTION_IDLE)
{
// Set the Intention of this L2AttackableAI to AI_INTENTION_IDLE
super.changeIntention(AI_INTENTION_IDLE, null, null);
// Stop AI task and detach AI from NPC
if (aiTask != null)
{
aiTask.cancel(true);
aiTask = null;
}
// Cancel the AI
_accessor.detachAI();
return;
}
}
// Set the Intention of this L2AttackableAI to intention
super.changeIntention(intention, arg0, arg1);
// If not idle - create an AI task (schedule onEvtThink repeatedly)
if (aiTask == null)
{
aiTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(this, 1000, 1000);
}
}
/**
* Manage the Attack Intention : Stop current Attack (if necessary), Calculate attack timeout, Start a new Attack and Launch Think Event.<BR>
* <BR>
* @param target The L2Character to attack
*/
@Override
protected void onIntentionAttack(L2Character target)
{
// Calculate the attack timeout
_attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
// Manage the Attack Intention : Stop current Attack (if necessary), Start a new Attack and Launch Think Event
// if (_actor.getTarget() != null)
super.onIntentionAttack(target);
}
/**
* Manage AI standard thinks of a L2Attackable (called by onEvtThink).<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Update every 1s the _globalAggro counter to come close to 0</li>
* <li>If the actor is Aggressive and can attack, add all autoAttackable L2Character in its Aggro Range to its _aggroList, chose a target and order to attack it</li>
* <li>If the actor can't attack, order to it to return to its home location</li>
*/
private void thinkActive()
{
final L2Attackable npc = (L2Attackable) _actor;
// Update every 1s the _globalAggro counter to come close to 0
if (_globalAggro != 0)
{
if (_globalAggro < 0)
{
_globalAggro++;
}
else
{
_globalAggro--;
}
}
// Add all autoAttackable L2Character in L2Attackable Aggro Range to its _aggroList with 0 damage and 1 hate
// A L2Attackable isn't aggressive during 10s after its spawn because _globalAggro is set to -10
if (_globalAggro >= 0)
{
for (final L2Character target : npc.getKnownList().getKnownCharactersInRadius(attackRange))
{
if (target == null)
{
continue;
}
if (autoAttackCondition(target)) // check aggression
{
// Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
final int hating = npc.getHating(target);
// Add the attacker to the L2Attackable _aggroList with 0 damage and 1 hate
if (hating == 0)
{
npc.addDamageHate(target, 0, 1);
}
}
}
// Chose a target from its aggroList
L2Character hated;
if (_actor.isConfused())
{
hated = _attack_target; // Force mobs to attack anybody if confused
}
else
{
hated = npc.getMostHated();
}
// Order to the L2Attackable to attack the target
if (hated != null)
{
// Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
final int aggro = npc.getHating(hated);
if ((aggro + _globalAggro) > 0)
{
// Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
if (!_actor.isRunning())
{
_actor.setRunning();
}
// Set the AI Intention to AI_INTENTION_ATTACK
setIntention(CtrlIntention.AI_INTENTION_ATTACK, hated, null);
}
return;
}
}
// Order to the L2SiegeGuardInstance to return to its home location because there's no target to attack
((L2SiegeGuardInstance) _actor).returnHome();
}
/**
* Manage AI attack thinks of a L2Attackable (called by onEvtThink).<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Update the attack timeout if actor is running</li>
* <li>If target is dead or timeout is expired, stop this attack and set the Intention to AI_INTENTION_ACTIVE</li>
* <li>Call all L2Object of its Faction inside the Faction Range</li>
* <li>Choose a target and order to attack it with magic skill or physical attack</li><BR>
* <BR>
* TODO: Manage casting rules to healer mobs (like Ant Nurses)
*/
private void thinkAttack()
{
if (Config.DEBUG)
{
_log.info("L2SiegeGuardAI.thinkAttack(); timeout=" + (_attackTimeout - GameTimeController.getGameTicks()));
}
if (_attackTimeout < GameTimeController.getGameTicks())
{
// Check if the actor is running
if (_actor.isRunning())
{
// Set the actor movement type to walk and send Server->Client packet ChangeMoveType to all others L2PcInstance
_actor.setWalking();
// Calculate a new attack timeout
_attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
}
}
// Check if target is dead or if timeout is expired to stop this attack
if ((_attack_target == null) || _attack_target.isAlikeDead() || (_attackTimeout < GameTimeController.getGameTicks()))
{
// Stop hating this target after the attack timeout or if target is dead
if (_attack_target != null)
{
final L2Attackable npc = (L2Attackable) _actor;
npc.stopHating(_attack_target);
}
// Cancel target and timeout
_attackTimeout = Integer.MAX_VALUE;
_attack_target = null;
// Set the AI Intention to AI_INTENTION_ACTIVE
setIntention(AI_INTENTION_ACTIVE, null, null);
_actor.setWalking();
return;
}
factionNotifyAndSupport();
attackPrepare();
}
private final void factionNotifyAndSupport()
{
final L2Character target = getAttackTarget();
// Call all L2Object of its Faction inside the Faction Range
if ((((L2NpcInstance) _actor).getFactionId() == null) || (target == null) || (_actor == null))
{
return;
}
if (target.isInvul())
{
return; // speeding it up for siege guards
}
final String faction_id = ((L2NpcInstance) _actor).getFactionId();
// Go through all L2Character that belong to its faction
for (final L2Character cha : _actor.getKnownList().getKnownCharactersInRadius(1000))
{
if (cha == null)
{
continue;
}
if (!(cha instanceof L2NpcInstance))
{
if (_selfAnalysis.hasHealOrResurrect && (cha instanceof L2PcInstance) && ((L2NpcInstance) _actor).getCastle().getSiege().checkIsDefender(((L2PcInstance) cha).getClan()))
{
// heal friends
if (!_actor.isAttackingDisabled() && (cha.getCurrentHp() < (cha.getMaxHp() * 0.6)) && (_actor.getCurrentHp() > (_actor.getMaxHp() / 2)) && (_actor.getCurrentMp() > (_actor.getMaxMp() / 2)) && cha.isInCombat())
{
for (final L2Skill sk : _selfAnalysis.healSkills)
{
if (_actor.getCurrentMp() < sk.getMpConsume())
{
continue;
}
if (_actor.isSkillDisabled(sk.getId()))
{
continue;
}
if (!Util.checkIfInRange(sk.getCastRange(), _actor, cha, true))
{
continue;
}
final int chance = 5;
if (chance >= Rnd.get(100))
{
continue;
}
if (!GeoData.getInstance().canSeeTarget(_actor, cha))
{
break;
}
final L2Object OldTarget = _actor.getTarget();
_actor.setTarget(cha);
clientStopMoving(null);
_accessor.doCast(sk);
_actor.setTarget(OldTarget);
return;
}
}
}
continue;
}
final L2NpcInstance npc = (L2NpcInstance) cha;
if (faction_id != npc.getFactionId())
{
continue;
}
if (npc.getAI() != null) // TODO: possibly check not needed
{
if ((Math.abs(target.getZ() - npc.getZ()) < 600) && ((npc.getAI()._intention == CtrlIntention.AI_INTENTION_IDLE) || (npc.getAI()._intention == CtrlIntention.AI_INTENTION_ACTIVE))
// limiting aggro for siege guards
&& target.isInsideRadius(npc, 1500, true, false) && GeoData.getInstance().canSeeTarget(npc, target))
{
// Notify the L2Object AI with EVT_AGGRESSION
npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, getAttackTarget(), 1);
}
// heal friends
if (_selfAnalysis.hasHealOrResurrect && !_actor.isAttackingDisabled() && (npc.getCurrentHp() < (npc.getMaxHp() * 0.6)) && (_actor.getCurrentHp() > (_actor.getMaxHp() / 2)) && (_actor.getCurrentMp() > (_actor.getMaxMp() / 2)) && npc.isInCombat())
{
for (final L2Skill sk : _selfAnalysis.healSkills)
{
if (_actor.getCurrentMp() < sk.getMpConsume())
{
continue;
}
if (_actor.isSkillDisabled(sk.getId()))
{
continue;
}
if (!Util.checkIfInRange(sk.getCastRange(), _actor, npc, true))
{
continue;
}
final int chance = 4;
if (chance >= Rnd.get(100))
{
continue;
}
if (!GeoData.getInstance().canSeeTarget(_actor, npc))
{
break;
}
final L2Object OldTarget = _actor.getTarget();
_actor.setTarget(npc);
clientStopMoving(null);
_accessor.doCast(sk);
_actor.setTarget(OldTarget);
return;
}
}
}
}
}
private void attackPrepare()
{
// Get all information needed to choose between physical or magical attack
L2Skill[] skills = null;
double dist_2 = 0;
int range = 0;
final L2SiegeGuardInstance sGuard = (L2SiegeGuardInstance) _actor;
try
{
_actor.setTarget(_attack_target);
skills = _actor.getAllSkills();
dist_2 = _actor.getPlanDistanceSq(_attack_target.getX(), _attack_target.getY());
range = _actor.getPhysicalAttackRange() + (int) (_actor.getTemplate().collisionRadius + _attack_target.getTemplate().collisionRadius);
if (_attack_target.isMoving())
{
range += 50;
}
}
catch (final NullPointerException e)
{
// _log.warning("AttackableAI: Attack target is NULL.");
_actor.setTarget(null);
setIntention(AI_INTENTION_IDLE, null, null);
return;
}
// never attack defenders
if ((_attack_target instanceof L2PcInstance) && sGuard.getCastle().getSiege().checkIsDefender(((L2PcInstance) _attack_target).getClan()))
{
// Cancel the target
sGuard.stopHating(_attack_target);
_actor.setTarget(null);
setIntention(AI_INTENTION_IDLE, null, null);
return;
}
if (!GeoData.getInstance().canSeeTarget(_actor, _attack_target))
{
// Siege guards differ from normal mobs currently:
// If target cannot be seen, don't attack any more
sGuard.stopHating(_attack_target);
_actor.setTarget(null);
setIntention(AI_INTENTION_IDLE, null, null);
return;
}
// Check if the actor isn't muted and if it is far from target
if (!_actor.isMuted() && (dist_2 > (range * range)))
{
// check for long ranged skills and heal/buff skills
for (final L2Skill sk : skills)
{
final int castRange = sk.getCastRange();
if ((dist_2 <= (castRange * castRange)) && (castRange > 70) && !_actor.isSkillDisabled(sk.getId()) && (_actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk)) && !sk.isPassive())
{
final L2Object OldTarget = _actor.getTarget();
if ((sk.getSkillType() == L2Skill.SkillType.BUFF) || (sk.getSkillType() == L2Skill.SkillType.HEAL))
{
boolean useSkillSelf = true;
if ((sk.getSkillType() == L2Skill.SkillType.HEAL) && (_actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5)))
{
useSkillSelf = false;
break;
}
if (sk.getSkillType() == L2Skill.SkillType.BUFF)
{
final L2Effect[] effects = _actor.getAllEffects();
for (int i = 0; (effects != null) && (i < effects.length); i++)
{
final L2Effect effect = effects[i];
if (effect.getSkill() == sk)
{
useSkillSelf = false;
break;
}
}
}
if (useSkillSelf)
{
_actor.setTarget(_actor);
}
}
clientStopMoving(null);
_accessor.doCast(sk);
_actor.setTarget(OldTarget);
return;
}
}
// Check if the L2SiegeGuardInstance is attacking, knows the target and can't run
if (!(_actor.isAttackingNow()) && (_actor.getRunSpeed() == 0) && (_actor.getKnownList().knowsObject(_attack_target)))
{
// Cancel the target
_actor.getKnownList().removeKnownObject(_attack_target);
_actor.setTarget(null);
setIntention(AI_INTENTION_IDLE, null, null);
}
else
{
final double dx = _actor.getX() - _attack_target.getX();
final double dy = _actor.getY() - _attack_target.getY();
final double dz = _actor.getZ() - _attack_target.getZ();
final double homeX = _attack_target.getX() - sGuard.getSpawn().getLocx();
final double homeY = _attack_target.getY() - sGuard.getSpawn().getLocy();
// Check if the L2SiegeGuardInstance isn't too far from it's home location
if ((((dx * dx) + (dy * dy)) > 10000) && (((homeX * homeX) + (homeY * homeY)) > 3240000) // 1800 * 1800
&& (_actor.getKnownList().knowsObject(_attack_target)))
{
// Cancel the target
_actor.getKnownList().removeKnownObject(_attack_target);
_actor.setTarget(null);
setIntention(AI_INTENTION_IDLE, null, null);
}
else // Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn (broadcast)
{
// Temporary hack for preventing guards jumping off towers,
// before replacing this with effective geodata checks and AI modification
if ((dz * dz) < (170 * 170)) // normally 130 if guard z coordinates correct
{
if (_selfAnalysis.isMage)
{
range = _selfAnalysis.maxCastRange - 50;
}
if (_attack_target.isMoving())
{
moveToPawn(_attack_target, range - 70);
}
else
{
moveToPawn(_attack_target, range);
}
}
}
}
return;
}
// Else, if the actor is muted and far from target, just "move to pawn"
else if (_actor.isMuted() && (dist_2 > (range * range)))
{
// Temporary hack for preventing guards jumping off towers,
// before replacing this with effective geodata checks and AI modification
final double dz = _actor.getZ() - _attack_target.getZ();
if ((dz * dz) < (170 * 170)) // normally 130 if guard z coordinates correct
{
if (_selfAnalysis.isMage)
{
range = _selfAnalysis.maxCastRange - 50;
}
if (_attack_target.isMoving())
{
moveToPawn(_attack_target, range - 70);
}
else
{
moveToPawn(_attack_target, range);
}
}
return;
}
// Else, if this is close enough to attack
else if (dist_2 <= (range * range))
{
// Force mobs to attack anybody if confused
L2Character hated = null;
if (_actor.isConfused())
{
hated = _attack_target;
}
else
{
hated = ((L2Attackable) _actor).getMostHated();
}
if (hated == null)
{
setIntention(AI_INTENTION_ACTIVE, null, null);
return;
}
if (hated != _attack_target)
{
_attack_target = hated;
}
_attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
// check for close combat skills && heal/buff skills
if (!_actor.isMuted() && (Rnd.nextInt(100) <= 5))
{
for (final L2Skill sk : skills)
{
final int castRange = sk.getCastRange();
if (((castRange * castRange) >= dist_2) && !sk.isPassive() && (_actor.getCurrentMp() >= _actor.getStat().getMpConsume(sk)) && !_actor.isSkillDisabled(sk.getId()))
{
final L2Object OldTarget = _actor.getTarget();
if ((sk.getSkillType() == L2Skill.SkillType.BUFF) || (sk.getSkillType() == L2Skill.SkillType.HEAL))
{
boolean useSkillSelf = true;
if ((sk.getSkillType() == L2Skill.SkillType.HEAL) && (_actor.getCurrentHp() > (int) (_actor.getMaxHp() / 1.5)))
{
useSkillSelf = false;
break;
}
if (sk.getSkillType() == L2Skill.SkillType.BUFF)
{
final L2Effect[] effects = _actor.getAllEffects();
for (int i = 0; (effects != null) && (i < effects.length); i++)
{
final L2Effect effect = effects[i];
if (effect.getSkill() == sk)
{
useSkillSelf = false;
break;
}
}
}
if (useSkillSelf)
{
_actor.setTarget(_actor);
}
}
clientStopMoving(null);
_accessor.doCast(sk);
_actor.setTarget(OldTarget);
return;
}
}
}
// Finally, do the physical attack itself
_accessor.doAttack(_attack_target);
}
}
/**
* Manage AI thinking actions of a L2Attackable.<BR>
* <BR>
*/
@Override
protected void onEvtThink()
{
// Check if the actor can't use skills and if a thinking action isn't already in progress
if (thinking || _actor.isAllSkillsDisabled())
{
return;
}
// Start thinking action
thinking = true;
try
{
// Manage AI thinks of a L2Attackable
if (getIntention() == AI_INTENTION_ACTIVE)
{
thinkActive();
}
else if (getIntention() == AI_INTENTION_ATTACK)
{
thinkAttack();
}
}
finally
{
// Stop thinking action
thinking = false;
}
}
/**
* Launch actions corresponding to the Event Attacked.<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Init the attack : Calculate the attack timeout, Set the _globalAggro to 0, Add the attacker to the actor _aggroList</li>
* <li>Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance</li>
* <li>Set the Intention to AI_INTENTION_ATTACK</li><BR>
* <BR>
* @param attacker The L2Character that attacks the actor
*/
@Override
protected void onEvtAttacked(L2Character attacker)
{
if (attacker == null)
{
return;
}
// Calculate the attack timeout
_attackTimeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();
// Set the _globalAggro to 0 to permit attack even just after spawn
if (_globalAggro < 0)
{
_globalAggro = 0;
}
// Add the attacker to the _aggroList of the actor
((L2Attackable) _actor).addDamageHate(attacker, 0, 1);
// Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
if (!_actor.isRunning())
{
_actor.setRunning();
}
// Set the Intention to AI_INTENTION_ATTACK
if (getIntention() != AI_INTENTION_ATTACK)
{
setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker, null);
}
super.onEvtAttacked(attacker);
}
/**
* Launch actions corresponding to the Event Aggression.<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Add the target to the actor _aggroList or update hate if already present</li>
* <li>Set the actor Intention to AI_INTENTION_ATTACK (if actor is L2GuardInstance check if it isn't too far from its home location)</li><BR>
* <BR>
* @param target The L2Character that attacks
* @param aggro The value of hate to add to the actor against the target
*/
@Override
protected void onEvtAggression(L2Character target, int aggro)
{
if (_actor == null)
{
return;
}
final L2Attackable me = (L2Attackable) _actor;
if (target != null)
{
// Add the target to the actor _aggroList or update hate if already present
me.addDamageHate(target, 0, aggro);
// Get the hate of the actor against the target
aggro = me.getHating(target);
if (aggro <= 0)
{
if (me.getMostHated() == null)
{
_globalAggro = -25;
me.clearAggroList();
setIntention(AI_INTENTION_IDLE, null, null);
}
return;
}
// Set the actor AI Intention to AI_INTENTION_ATTACK
if (getIntention() != CtrlIntention.AI_INTENTION_ATTACK)
{
// Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
if (!_actor.isRunning())
{
_actor.setRunning();
}
final L2SiegeGuardInstance sGuard = (L2SiegeGuardInstance) _actor;
final double homeX = target.getX() - sGuard.getSpawn().getLocx();
final double homeY = target.getY() - sGuard.getSpawn().getLocy();
// Check if the L2SiegeGuardInstance is not too far from its home location
if (((homeX * homeX) + (homeY * homeY)) < 3240000)
{
setIntention(CtrlIntention.AI_INTENTION_ATTACK, target, null);
}
}
}
else
{
// currently only for setting lower general aggro
if (aggro >= 0)
{
return;
}
final L2Character mostHated = me.getMostHated();
if (mostHated == null)
{
_globalAggro = -25;
return;
}
for (final L2Character aggroed : me.getAggroList().keySet())
{
me.addDamageHate(aggroed, 0, aggro);
}
aggro = me.getHating(mostHated);
if (aggro <= 0)
{
_globalAggro = -25;
me.clearAggroList();
setIntention(AI_INTENTION_IDLE, null, null);
}
}
}
@Override
protected void onEvtDead()
{
stopAITask();
super.onEvtDead();
}
public void stopAITask()
{
if (aiTask != null)
{
aiTask.cancel(false);
aiTask = null;
}
_accessor.detachAI();
}
}

View File

@@ -0,0 +1,195 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.ai;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
import com.l2jmobius.gameserver.model.L2Character.AIAccessor;
import com.l2jmobius.gameserver.model.L2Summon;
public class L2SummonAI extends L2CharacterAI
{
private boolean thinking; // to prevent recursive thinking
private boolean _previousFollowStatus = ((L2Summon) _actor).getFollowStatus();
public L2SummonAI(AIAccessor accessor)
{
super(accessor);
}
@Override
protected void onIntentionIdle()
{
stopFollow();
_previousFollowStatus = false;
onIntentionActive();
}
@Override
protected void onIntentionActive()
{
final L2Summon summon = (L2Summon) _actor;
if (_previousFollowStatus)
{
setIntention(AI_INTENTION_FOLLOW, summon.getOwner());
}
else
{
super.onIntentionActive();
}
}
private void thinkAttack()
{
if (checkTargetLostOrDead(getAttackTarget()))
{
setAttackTarget(null);
return;
}
if (maybeMoveToPawn(getAttackTarget(), _actor.getPhysicalAttackRange()))
{
return;
}
clientStopMoving(null);
_accessor.doAttack(getAttackTarget());
}
private void thinkCast()
{
final L2Summon summon = (L2Summon) _actor;
if (checkTargetLost(getCastTarget()))
{
setCastTarget(null);
return;
}
final boolean val = _previousFollowStatus;
if (maybeMoveToPawn(getCastTarget(), _actor.getMagicalAttackRange(_skill)))
{
return;
}
clientStopMoving(null);
summon.setFollowStatus(false);
setIntention(AI_INTENTION_IDLE);
_previousFollowStatus = val;
_accessor.doCast(_skill);
}
private void thinkPickUp()
{
if (_actor.isAllSkillsDisabled())
{
return;
}
if (checkTargetLost(getTarget()))
{
return;
}
if (maybeMoveToPawn(getTarget(), 36))
{
return;
}
setIntention(AI_INTENTION_IDLE);
((L2Summon.AIAccessor) _accessor).doPickupItem(getTarget());
}
private void thinkInteract()
{
if (_actor.isAllSkillsDisabled())
{
return;
}
if (checkTargetLost(getTarget()))
{
return;
}
if (maybeMoveToPawn(getTarget(), 36))
{
return;
}
setIntention(AI_INTENTION_IDLE);
}
@Override
protected void onEvtThink()
{
if (thinking || _actor.isAllSkillsDisabled())
{
return;
}
thinking = true;
try
{
if (getIntention() == AI_INTENTION_ATTACK)
{
thinkAttack();
}
else if (getIntention() == AI_INTENTION_CAST)
{
thinkCast();
}
else if (getIntention() == AI_INTENTION_PICK_UP)
{
thinkPickUp();
}
else if (getIntention() == AI_INTENTION_INTERACT)
{
thinkInteract();
}
}
finally
{
thinking = false;
}
}
@Override
protected void onEvtFinishCasting()
{
if (_actor.getAI().getIntention() != AI_INTENTION_ATTACK)
{
((L2Summon) _actor).setFollowStatus(_previousFollowStatus);
}
}
public void notifyFollowStatusChange()
{
_previousFollowStatus = !_previousFollowStatus;
switch (getIntention())
{
case AI_INTENTION_ACTIVE:
case AI_INTENTION_FOLLOW:
case AI_INTENTION_IDLE:
((L2Summon) _actor).setFollowStatus(_previousFollowStatus);
break;
}
}
public void setStartFollowController(boolean val)
{
_previousFollowStatus = val;
}
}

View File

@@ -0,0 +1,323 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.cache;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.datatables.ClanTable;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.model.L2Clan;
import javolution.util.FastMap;
/**
* @author Layane
*/
public class CrestCache
{
private static Logger _log = Logger.getLogger(CrestCache.class.getName());
private static CrestCache _instance;
private final FastMRUCache<Integer, byte[]> _cachePledge = new FastMRUCache<>();
private final FastMRUCache<Integer, byte[]> _cachePledgeLarge = new FastMRUCache<>();
private final FastMRUCache<Integer, byte[]> _cacheAlly = new FastMRUCache<>();
private int _loadedFiles;
private long _bytesBuffLen;
public static CrestCache getInstance()
{
if (_instance == null)
{
_instance = new CrestCache();
}
return _instance;
}
public CrestCache()
{
convertOldPledgeFiles();
reload();
}
public void reload()
{
final FileFilter filter = new BmpFilter();
final File dir = new File(Config.DATAPACK_ROOT, "data/crests/");
final File[] files = dir.listFiles(filter);
byte[] content;
synchronized (this)
{
_loadedFiles = 0;
_bytesBuffLen = 0;
_cachePledge.clear();
_cachePledgeLarge.clear();
_cacheAlly.clear();
}
final FastMap<Integer, byte[]> _mapPledge = _cachePledge.getContentMap();
final FastMap<Integer, byte[]> _mapPledgeLarge = _cachePledgeLarge.getContentMap();
final FastMap<Integer, byte[]> _mapAlly = _cacheAlly.getContentMap();
for (final File file : files)
{
synchronized (this)
{
try (RandomAccessFile f = new RandomAccessFile(file, "r"))
{
content = new byte[(int) f.length()];
f.readFully(content);
if (file.getName().startsWith("Crest_Large_"))
{
_mapPledgeLarge.put(Integer.valueOf(file.getName().substring(12, file.getName().length() - 4)), content);
}
else if (file.getName().startsWith("Crest_"))
{
_mapPledge.put(Integer.valueOf(file.getName().substring(6, file.getName().length() - 4)), content);
}
else if (file.getName().startsWith("AllyCrest_"))
{
_mapAlly.put(Integer.valueOf(file.getName().substring(10, file.getName().length() - 4)), content);
}
_loadedFiles++;
_bytesBuffLen += content.length;
}
catch (final Exception e)
{
_log.warning("problem with crest bmp file " + e);
}
}
}
_log.info("Cache[Crest]: " + String.format("%.3f", getMemoryUsage()) + "MB on " + getLoadedFiles() + " files loaded. (Forget Time: " + (_cachePledge.getForgetTime() / 1000) + "s , Capacity: " + _cachePledge.capacity() + ")");
}
public void convertOldPledgeFiles()
{
final File dir = new File(Config.DATAPACK_ROOT, "data/crests/");
final File[] files = dir.listFiles(new OldPledgeFilter());
for (final File file : files)
{
final int clanId = Integer.parseInt(file.getName().substring(7, file.getName().length() - 4));
_log.info("Found old crest file \"" + file.getName() + "\" for clanId " + clanId);
final int newId = IdFactory.getInstance().getNextId();
final L2Clan clan = ClanTable.getInstance().getClan(clanId);
if (clan != null)
{
removeOldPledgeCrest(clan.getCrestId());
file.renameTo(new File(Config.DATAPACK_ROOT, "data/crests/Crest_" + newId + ".bmp"));
_log.info("Renamed Clan crest to new format: Crest_" + newId + ".bmp");
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("UPDATE clan_data SET crest_id = ? WHERE clan_id = ?"))
{
statement.setInt(1, newId);
statement.setInt(2, clan.getClanId());
statement.executeUpdate();
}
catch (final SQLException e)
{
_log.warning("could not update the crest id:" + e.getMessage());
}
clan.setCrestId(newId);
clan.setHasCrest(true);
}
else
{
_log.info("Clan Id: " + clanId + " does not exist in table.. deleting.");
file.delete();
}
}
}
public float getMemoryUsage()
{
return ((float) _bytesBuffLen / 1048576);
}
public int getLoadedFiles()
{
return _loadedFiles;
}
public byte[] getPledgeCrest(int id)
{
return _cachePledge.get(id);
}
public byte[] getPledgeCrestLarge(int id)
{
return _cachePledgeLarge.get(id);
}
public byte[] getAllyCrest(int id)
{
return _cacheAlly.get(id);
}
public void removePledgeCrest(int id)
{
final File crestFile = new File(Config.DATAPACK_ROOT, "data/crests/Crest_" + id + ".bmp");
_cachePledge.remove(id);
try
{
crestFile.delete();
}
catch (final Exception e)
{
}
}
public void removePledgeCrestLarge(int id)
{
final File crestFile = new File(Config.DATAPACK_ROOT, "data/crests/Crest_Large_" + id + ".bmp");
_cachePledgeLarge.remove(id);
try
{
crestFile.delete();
}
catch (final Exception e)
{
}
}
public void removeOldPledgeCrest(int id)
{
final File crestFile = new File(Config.DATAPACK_ROOT, "data/crests/Pledge_" + id + ".bmp");
try
{
crestFile.delete();
}
catch (final Exception e)
{
}
}
public void removeAllyCrest(int id)
{
final File crestFile = new File(Config.DATAPACK_ROOT, "data/crests/AllyCrest_" + id + ".bmp");
_cacheAlly.remove(id);
try
{
crestFile.delete();
}
catch (final Exception e)
{
}
}
public boolean savePledgeCrest(int newId, byte[] data)
{
final File crestFile = new File(Config.DATAPACK_ROOT, "data/crests/Crest_" + newId + ".bmp");
try (FileOutputStream out = new FileOutputStream(crestFile))
{
out.write(data);
_cachePledge.getContentMap().put(newId, data);
return true;
}
catch (final IOException e)
{
_log.log(Level.INFO, "Error saving pledge crest" + crestFile + ":", e);
return false;
}
}
public boolean savePledgeCrestLarge(int newId, byte[] data)
{
final File crestFile = new File(Config.DATAPACK_ROOT, "data/crests/Crest_Large_" + newId + ".bmp");
try (FileOutputStream out = new FileOutputStream(crestFile))
{
out.write(data);
_cachePledgeLarge.getContentMap().put(newId, data);
return true;
}
catch (final IOException e)
{
_log.log(Level.INFO, "Error saving Large pledge crest" + crestFile + ":", e);
return false;
}
}
public boolean saveAllyCrest(int newId, byte[] data)
{
final File crestFile = new File(Config.DATAPACK_ROOT, "data/crests/AllyCrest_" + newId + ".bmp");
try (FileOutputStream out = new FileOutputStream(crestFile))
{
out.write(data);
_cacheAlly.getContentMap().put(newId, data);
return true;
}
catch (final IOException e)
{
_log.log(Level.INFO, "Error saving ally crest" + crestFile + ":", e);
return false;
}
}
class BmpFilter implements FileFilter
{
@Override
public boolean accept(File file)
{
return (file.getName().endsWith(".bmp"));
}
}
class OldPledgeFilter implements FileFilter
{
@Override
public boolean accept(File file)
{
return (file.getName().startsWith("Pledge_"));
}
}
}

View File

@@ -0,0 +1,227 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.cache;
import javolution.context.ObjectFactory;
import javolution.lang.Reusable;
import javolution.util.FastCollection;
import javolution.util.FastComparator;
import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastMap.Entry;
/**
* @author Layane
* @param <K>
* @param <V>
*/
public class FastMRUCache<K, V>extends FastCollection<Object> implements Reusable
{
private static final long serialVersionUID = 1L;
public static final int DEFAULT_CAPACITY = 50;
public static final int DEFAULT_FORGET_TIME = 300000; // 5 Minutes
FastMap<K, CacheNode> _cache = new FastMap<K, CacheNode>().setKeyComparator(FastComparator.DIRECT);
FastMap<K, V> _map;
FastList<K> _mruList = new FastList<>();
int _cacheSize;
int _forgetTime;
class CacheNode
{
long lastModified;
V node;
public CacheNode(V object)
{
lastModified = System.currentTimeMillis();
node = object;
}
@Override
public boolean equals(Object object)
{
return node == object;
}
}
/**
* Holds the set factory.
*/
private static final ObjectFactory<?> FACTORY = new ObjectFactory<Object>()
{
@Override
public Object create()
{
return new FastMRUCache<>();
}
@Override
public void cleanup(Object obj)
{
((FastMRUCache<?, ?>) obj).reset();
}
};
/**
* Returns a set allocated from the stack when executing in a PoolContext}).
* @return a new, pre-allocated or recycled set instance.
*/
public static FastMRUCache<?, ?> newInstance()
{
return (FastMRUCache<?, ?>) FACTORY.object();
}
public FastMRUCache()
{
this(new FastMap<K, V>(), DEFAULT_CAPACITY, DEFAULT_FORGET_TIME);
}
public FastMRUCache(FastMap<K, V> map)
{
this(map, DEFAULT_CAPACITY, DEFAULT_FORGET_TIME);
}
public FastMRUCache(FastMap<K, V> map, int max)
{
this(map, max, DEFAULT_FORGET_TIME);
}
public FastMRUCache(FastMap<K, V> map, int max, int forgetTime)
{
_map = map;
_cacheSize = max;
_forgetTime = forgetTime;
_map.setKeyComparator(FastComparator.DIRECT);
}
// Implements Reusable.
@Override
public synchronized void reset()
{
_map.reset();
_cache.reset();
_mruList.reset();
_map.setKeyComparator(FastComparator.DIRECT);
_cache.setKeyComparator(FastComparator.DIRECT);
}
public synchronized V get(K key)
{
V result;
if (!_cache.containsKey(key))
{
if (_mruList.size() >= _cacheSize)
{
_cache.remove(_mruList.getLast());
_mruList.removeLast();
}
result = _map.get(key);
_cache.put(key, new CacheNode(result));
_mruList.addFirst(key);
}
else
{
final CacheNode current = _cache.get(key);
if ((current.lastModified + _forgetTime) <= System.currentTimeMillis())
{
current.lastModified = System.currentTimeMillis();
current.node = _map.get(key);
_cache.put(key, current);
}
_mruList.remove(key);
_mruList.addFirst(key);
result = current.node;
}
return result;
}
@Override
public synchronized boolean remove(Object key)
{
_cache.remove(key);
_mruList.remove(key);
return _map.remove(key) == key;
}
public FastMap<K, V> getContentMap()
{
return _map;
}
@Override
public int size()
{
return _mruList.size();
}
public int capacity()
{
return _cacheSize;
}
public int getForgetTime()
{
return _forgetTime;
}
@Override
public synchronized void clear()
{
_cache.clear();
_mruList.clear();
_map.clear();
}
// Implements FastCollection abstract method.
@Override
public final Record head()
{
return _mruList.head();
}
@Override
public final Record tail()
{
return _mruList.tail();
}
@Override
public final Object valueOf(Record record)
{
return ((Entry<?, ?>) record).getKey();
}
@Override
public final void delete(Record record)
{
remove(((Entry<?, ?>) record).getKey());
}
}

View File

@@ -0,0 +1,222 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.cache;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.util.Util;
import javolution.util.FastMap;
/**
* @author Layane
*/
public class HtmCache
{
private static Logger _log = Logger.getLogger(HtmCache.class.getName());
private static HtmCache _instance;
private final FastMap<Integer, String> _cache;
private int _loadedFiles;
private long _bytesBuffLen;
public static HtmCache getInstance()
{
if (_instance == null)
{
_instance = new HtmCache();
}
return _instance;
}
public HtmCache()
{
_cache = new FastMap<>();
reload();
}
public void reload()
{
reload(Config.DATAPACK_ROOT);
}
public void reload(File f)
{
if (!Config.LAZY_CACHE)
{
_log.info("Html cache start...");
parseDir(f);
_log.info("Cache[HTML]: " + String.format("%.3f", getMemoryUsage()) + " megabytes on " + getLoadedFiles() + " files loaded");
}
else
{
_cache.clear();
_loadedFiles = 0;
_bytesBuffLen = 0;
_log.info("Cache[HTML]: Running lazy cache");
}
}
public void reloadPath(File f)
{
parseDir(f);
_log.info("Cache[HTML]: Reloaded specified path.");
}
public double getMemoryUsage()
{
return ((float) _bytesBuffLen / 1048576);
}
public int getLoadedFiles()
{
return _loadedFiles;
}
class HtmFilter implements FileFilter
{
@Override
public boolean accept(File file)
{
if (!file.isDirectory())
{
return (file.getName().endsWith(".htm") || file.getName().endsWith(".html"));
}
return true;
}
}
private void parseDir(File dir)
{
final FileFilter filter = new HtmFilter();
final File[] files = dir.listFiles(filter);
for (final File file : files)
{
if (!file.isDirectory())
{
loadFile(file);
}
else
{
parseDir(file);
}
}
}
public String loadFile(File file)
{
final HtmFilter filter = new HtmFilter();
if (file.exists() && filter.accept(file) && !file.isDirectory())
{
String content;
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis))
{
final int bytes = bis.available();
final byte[] raw = new byte[bytes];
bis.read(raw);
content = new String(raw, "UTF-8");
content.replaceAll("\r\n", "\n");
final String relpath = Util.getRelativePath(Config.DATAPACK_ROOT, file);
final int hashcode = relpath.hashCode();
final String oldContent = _cache.get(hashcode);
if (oldContent == null)
{
_bytesBuffLen += bytes;
_loadedFiles++;
}
else
{
_bytesBuffLen = (_bytesBuffLen - oldContent.length()) + bytes;
}
_cache.put(hashcode, content);
return content;
}
catch (final Exception e)
{
_log.warning("problem with htm file " + e);
}
}
return null;
}
public String getHtmForce(String path)
{
String content = getHtm(path);
if (content == null)
{
content = "<html><body>My text is missing:<br>" + path + "</body></html>";
_log.warning("Cache[HTML]: Missing HTML page: " + path);
}
return content;
}
public String getHtm(String path)
{
String content = _cache.get(path.hashCode());
if (Config.LAZY_CACHE && (content == null))
{
content = loadFile(new File(Config.DATAPACK_ROOT, path));
}
return content;
}
public boolean contains(String path)
{
return _cache.containsKey(path.hashCode());
}
/**
* Check if an HTM exists and can be loaded
* @param path The path to the HTM
* @return
*/
public boolean isLoadable(String path)
{
final File file = new File(path);
final HtmFilter filter = new HtmFilter();
if (file.exists() && filter.accept(file) && !file.isDirectory())
{
return true;
}
return false;
}
}

View File

@@ -0,0 +1,76 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.cache;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import javolution.util.FastMap;
/**
* @author -Nemesiss-
*/
public class WarehouseCacheManager
{
private static WarehouseCacheManager _instance;
protected final FastMap<L2PcInstance, Long> _CachedWh;
protected final long _CacheTime;
public static WarehouseCacheManager getInstance()
{
if (_instance == null)
{
_instance = new WarehouseCacheManager();
}
return _instance;
}
private WarehouseCacheManager()
{
_CacheTime = Config.WAREHOUSE_CACHE_TIME * 60 * 1000;
_CachedWh = new FastMap<L2PcInstance, Long>().shared();
ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new CacheScheduler(), 120000, 60000);
}
public void addCacheTask(L2PcInstance pc)
{
_CachedWh.put(pc, System.currentTimeMillis());
}
public void remCacheTask(L2PcInstance pc)
{
_CachedWh.remove(pc);
}
public class CacheScheduler implements Runnable
{
@Override
public void run()
{
final long cTime = System.currentTimeMillis();
for (final L2PcInstance pc : _CachedWh.keySet())
{
if ((cTime - _CachedWh.get(pc)) > _CacheTime)
{
pc.clearWarehouse();
_CachedWh.remove(pc);
}
}
}
}
}

View File

@@ -0,0 +1,272 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.BB;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.communitybbs.Manager.ForumsBBSManager;
import com.l2jmobius.gameserver.communitybbs.Manager.TopicBBSManager;
import javolution.util.FastList;
import javolution.util.FastMap;
public class Forum
{
// type
public static final int ROOT = 0;
public static final int NORMAL = 1;
public static final int CLAN = 2;
public static final int MEMO = 3;
public static final int MAIL = 4;
// perm
public static final int INVISIBLE = 0;
public static final int ALL = 1;
public static final int CLANMEMBERONLY = 2;
public static final int OWNERONLY = 3;
private static Logger _log = Logger.getLogger(Forum.class.getName());
private final List<Forum> _children;
private final Map<Integer, Topic> _topic;
private final int _ForumId;
private String _ForumName;
// private int _ForumParent;
private int _ForumType;
private int _ForumPost;
private int _ForumPerm;
private final Forum _FParent;
private int _OwnerID;
private boolean loaded = false;
/**
* @param Forumid
* @param FParent
*/
public Forum(int Forumid, Forum FParent)
{
_ForumId = Forumid;
_FParent = FParent;
_children = new FastList<>();
_topic = new FastMap<>();
}
/**
* @param name
* @param parent
* @param type
* @param perm
* @param OwnerID
*/
public Forum(String name, Forum parent, int type, int perm, int OwnerID)
{
_ForumName = name;
_ForumId = ForumsBBSManager.getInstance().GetANewID();
// _ForumParent = parent.getID();
_ForumType = type;
_ForumPost = 0;
_ForumPerm = perm;
_FParent = parent;
_OwnerID = OwnerID;
_children = new FastList<>();
_topic = new FastMap<>();
parent._children.add(this);
ForumsBBSManager.getInstance().addForum(this);
loaded = true;
}
/**
*
*/
private void load()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM forums WHERE forum_id=?"))
{
statement.setInt(1, _ForumId);
try (ResultSet result = statement.executeQuery())
{
if (result.next())
{
_ForumName = result.getString("forum_name");
_ForumPost = result.getInt("forum_post");
_ForumType = result.getInt("forum_type");
_ForumPerm = result.getInt("forum_perm");
_OwnerID = result.getInt("forum_owner_id");
}
}
}
catch (final Exception e)
{
_log.warning("data error on Forum " + _ForumId + " : " + e);
e.printStackTrace();
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM topic WHERE topic_forum_id=? ORDER BY topic_id DESC"))
{
statement.setInt(1, _ForumId);
try (ResultSet result = statement.executeQuery())
{
while (result.next())
{
final Topic t = new Topic(Topic.ConstructorType.RESTORE, result.getInt("topic_id"), result.getInt("topic_forum_id"), result.getString("topic_name"), result.getLong("topic_date"), result.getString("topic_ownername"), result.getInt("topic_ownerid"), result.getInt("topic_type"), result.getInt("topic_reply"));
_topic.put(t.getID(), t);
if (t.getID() > TopicBBSManager.getInstance().getMaxID(this))
{
TopicBBSManager.getInstance().setMaxID(t.getID(), this);
}
}
}
}
catch (final Exception e)
{
_log.warning("data error on Forum " + _ForumId + " : " + e);
e.printStackTrace();
}
}
/**
*
*/
private void getChildren()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT forum_id FROM forums WHERE forum_parent=?"))
{
statement.setInt(1, _ForumId);
try (ResultSet result = statement.executeQuery())
{
while (result.next())
{
final Forum f = new Forum(result.getInt("forum_id"), this);
_children.add(f);
ForumsBBSManager.getInstance().addForum(f);
}
}
}
catch (final Exception e)
{
_log.warning("data error on Forum (children): " + e);
e.printStackTrace();
}
}
public int getTopicSize()
{
vload();
return _topic.size();
}
public Topic gettopic(int j)
{
vload();
return _topic.get(j);
}
public void addtopic(Topic t)
{
vload();
_topic.put(t.getID(), t);
}
/**
* @return
*/
public int getID()
{
return _ForumId;
}
public String getName()
{
vload();
return _ForumName;
}
public int getType()
{
vload();
return _ForumType;
}
/**
* @param name
* @return
*/
public Forum GetChildByName(String name)
{
vload();
for (final Forum f : _children)
{
if (f.getName().equals(name))
{
return f;
}
}
return null;
}
/**
* @param id
*/
public void RmTopicByID(int id)
{
_topic.remove(id);
}
/**
*
*/
public void insertindb()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO forums (forum_id,forum_name,forum_parent,forum_post,forum_type,forum_perm,forum_owner_id) values (?,?,?,?,?,?,?)"))
{
statement.setInt(1, _ForumId);
statement.setString(2, _ForumName);
statement.setInt(3, _FParent.getID());
statement.setInt(4, _ForumPost);
statement.setInt(5, _ForumType);
statement.setInt(6, _ForumPerm);
statement.setInt(7, _OwnerID);
statement.execute();
}
catch (final Exception e)
{
_log.warning("error while saving new Forum to db " + e);
}
}
/**
*
*/
public void vload()
{
if (loaded == false)
{
load();
getChildren();
loaded = true;
}
}
}

View File

@@ -0,0 +1,176 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.BB;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.communitybbs.Manager.PostBBSManager;
import javolution.util.FastList;
/**
* @author Maktakien
*/
public class Post
{
private static Logger _log = Logger.getLogger(Post.class.getName());
public class CPost
{
public int _PostID;
public String _PostOwner;
public int _PostOwnerID;
public long _PostDate;
public int _PostTopicID;
public int _PostForumID;
public String _PostTxt;
}
private final List<CPost> _post;
public Post(String _PostOwner, int _PostOwnerID, long date, int tid, int _PostForumID, String txt)
{
_post = new FastList<>();
final CPost cp = new CPost();
cp._PostID = 0;
cp._PostOwner = _PostOwner;
cp._PostOwnerID = _PostOwnerID;
cp._PostDate = date;
cp._PostTopicID = tid;
cp._PostForumID = _PostForumID;
cp._PostTxt = txt;
_post.add(cp);
insertindb(cp);
}
public void insertindb(CPost cp)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO posts (post_id,post_owner_name,post_ownerid,post_date,post_topic_id,post_forum_id,post_txt) values (?,?,?,?,?,?,?)"))
{
statement.setInt(1, cp._PostID);
statement.setString(2, cp._PostOwner);
statement.setInt(3, cp._PostOwnerID);
statement.setLong(4, cp._PostDate);
statement.setInt(5, cp._PostTopicID);
statement.setInt(6, cp._PostForumID);
statement.setString(7, cp._PostTxt);
statement.execute();
}
catch (final Exception e)
{
_log.warning("error while saving new Post to db " + e);
}
}
public Post(Topic t)
{
_post = new FastList<>();
load(t);
}
public CPost getCPost(int id)
{
int i = 0;
for (final CPost cp : _post)
{
if (i++ == id)
{
return cp;
}
}
return null;
}
public void deleteme(Topic t)
{
PostBBSManager.getInstance().delPostByTopic(t);
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM posts WHERE post_forum_id=? AND post_topic_id=?"))
{
statement.setInt(1, t.getForumID());
statement.setInt(2, t.getID());
statement.execute();
}
catch (final Exception e)
{
e.printStackTrace();
}
}
/**
* @param t
*/
private void load(Topic t)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM posts WHERE post_forum_id=? AND post_topic_id=? ORDER BY post_id ASC"))
{
statement.setInt(1, t.getForumID());
statement.setInt(2, t.getID());
try (ResultSet result = statement.executeQuery())
{
while (result.next())
{
final CPost cp = new CPost();
cp._PostID = Integer.parseInt(result.getString("post_id"));
cp._PostOwner = result.getString("post_owner_name");
cp._PostOwnerID = Integer.parseInt(result.getString("post_ownerid"));
cp._PostDate = Long.parseLong(result.getString("post_date"));
cp._PostTopicID = Integer.parseInt(result.getString("post_topic_id"));
cp._PostForumID = Integer.parseInt(result.getString("post_forum_id"));
cp._PostTxt = result.getString("post_txt");
_post.add(cp);
}
}
}
catch (final Exception e)
{
_log.warning("data error on Post " + t.getForumID() + "/" + t.getID() + " : " + e);
e.printStackTrace();
}
}
/**
* @param i
*/
public void updatetxt(int i)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("UPDATE posts SET post_txt=? WHERE post_id=? AND post_topic_id=? AND post_forum_id=?"))
{
final CPost cp = getCPost(i);
statement.setString(1, cp._PostTxt);
statement.setInt(2, cp._PostID);
statement.setInt(3, cp._PostTopicID);
statement.setInt(4, cp._PostForumID);
statement.execute();
}
catch (final Exception e)
{
_log.warning("error while saving new Post to db " + e);
}
}
}

View File

@@ -0,0 +1,153 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.BB;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.communitybbs.Manager.TopicBBSManager;
public class Topic
{
private static Logger _log = Logger.getLogger(Topic.class.getName());
public static final int MORMAL = 0;
public static final int MEMO = 1;
private final int _ID;
private final int _ForumID;
private final String _TopicName;
private final long _date;
private final String _OwnerName;
private final int _OwnerID;
private final int _type;
private final int _Creply;
/**
* @param ct
* @param id
* @param fid
* @param name
* @param date
* @param oname
* @param oid
* @param type
* @param Creply
*/
public Topic(ConstructorType ct, int id, int fid, String name, long date, String oname, int oid, int type, int Creply)
{
_ID = id;
_ForumID = fid;
_TopicName = name;
_date = date;
_OwnerName = oname;
_OwnerID = oid;
_type = type;
_Creply = Creply;
TopicBBSManager.getInstance().addTopic(this);
if (ct == ConstructorType.CREATE)
{
insertindb();
}
}
/**
*
*/
public void insertindb()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO topic (topic_id,topic_forum_id,topic_name,topic_date,topic_ownername,topic_ownerid,topic_type,topic_reply) values (?,?,?,?,?,?,?,?)"))
{
statement.setInt(1, _ID);
statement.setInt(2, _ForumID);
statement.setString(3, _TopicName);
statement.setLong(4, _date);
statement.setString(5, _OwnerName);
statement.setInt(6, _OwnerID);
statement.setInt(7, _type);
statement.setInt(8, _Creply);
statement.execute();
}
catch (final Exception e)
{
_log.warning("error while saving new Topic to db " + e);
}
}
public enum ConstructorType
{
RESTORE,
CREATE
}
/**
* @return
*/
public int getID()
{
return _ID;
}
public int getForumID()
{
return _ForumID;
}
/**
* @return
*/
public String getName()
{
// TODO Auto-generated method stub
return _TopicName;
}
public String getOwnerName()
{
// TODO Auto-generated method stub
return _OwnerName;
}
public void deleteme(Forum f)
{
TopicBBSManager.getInstance().delTopic(this);
f.RmTopicByID(getID());
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM topic WHERE topic_id=? AND topic_forum_id=?"))
{
statement.setInt(1, getID());
statement.setInt(2, f.getID());
statement.execute();
}
catch (final Exception e)
{
e.printStackTrace();
}
}
/**
* @return
*/
public long getDate()
{
return _date;
}
}

View File

@@ -0,0 +1,151 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.communitybbs.Manager.ClanBBSManager;
import com.l2jmobius.gameserver.communitybbs.Manager.PostBBSManager;
import com.l2jmobius.gameserver.communitybbs.Manager.RegionBBSManager;
import com.l2jmobius.gameserver.communitybbs.Manager.TopBBSManager;
import com.l2jmobius.gameserver.communitybbs.Manager.TopicBBSManager;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.serverpackets.ShowBoard;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public class CommunityBoard
{
private static CommunityBoard _instance;
public static CommunityBoard getInstance()
{
if (_instance == null)
{
_instance = new CommunityBoard();
}
return _instance;
}
public void handleCommands(L2GameClient client, String command)
{
final L2PcInstance activeChar = client.getActiveChar();
if (activeChar == null)
{
return;
}
switch (Config.COMMUNITY_TYPE)
{
default:
case 0: // disabled
activeChar.sendPacket(new SystemMessage(SystemMessage.CB_OFFLINE));
break;
case 1: // old
RegionBBSManager.getInstance().parsecmd(command, activeChar);
case 2: // new
if (command.startsWith("_bbsclan"))
{
ClanBBSManager.getInstance().parsecmd(command, activeChar);
}
else if (command.startsWith("_bbsmemo"))
{
TopicBBSManager.getInstance().parsecmd(command, activeChar);
}
else if (command.startsWith("_bbstopics"))
{
TopicBBSManager.getInstance().parsecmd(command, activeChar);
}
else if (command.startsWith("_bbsposts"))
{
PostBBSManager.getInstance().parsecmd(command, activeChar);
}
else if (command.startsWith("_bbstop"))
{
TopBBSManager.getInstance().parsecmd(command, activeChar);
}
else if (command.startsWith("_bbshome"))
{
TopBBSManager.getInstance().parsecmd(command, activeChar);
}
else if (command.startsWith("_bbsloc"))
{
RegionBBSManager.getInstance().parsecmd(command, activeChar);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
break;
}
}
/**
* @param client
* @param url
* @param arg1
* @param arg2
* @param arg3
* @param arg4
* @param arg5
*/
public void handleWriteCommands(L2GameClient client, String url, String arg1, String arg2, String arg3, String arg4, String arg5)
{
final L2PcInstance activeChar = client.getActiveChar();
if (activeChar == null)
{
return;
}
switch (Config.COMMUNITY_TYPE)
{
case 2:
if (url.equals("Topic"))
{
TopicBBSManager.getInstance().parsewrite(arg1, arg2, arg3, arg4, arg5, activeChar);
}
else if (url.equals("Post"))
{
PostBBSManager.getInstance().parsewrite(arg1, arg2, arg3, arg4, arg5, activeChar);
}
else if (url.equals("Region"))
{
RegionBBSManager.getInstance().parsewrite(arg1, arg2, arg3, arg4, arg5, activeChar);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + url + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
break;
case 1:
RegionBBSManager.getInstance().parsewrite(arg1, arg2, arg3, arg4, arg5, activeChar);
break;
default:
case 0:
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>The Community board is currently disabled.</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
break;
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ShowBoard;
public class AdminBBSManager extends BaseBBSManager
{
private static AdminBBSManager _Instance = null;
/**
* @return
*/
public static AdminBBSManager getInstance()
{
if (_Instance == null)
{
_Instance = new AdminBBSManager();
}
return _Instance;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsecmd(String command, L2PcInstance activeChar)
{
if (!activeChar.isGM())
{
return;
}
if (command.startsWith("admin_bbs"))
{
separateAndSend("<html><body><br><br><center>This Page is only an exemple :)<br><br>command=" + command + "</center></body></html>", activeChar);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
@Override
public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
{
if (!activeChar.isGM())
{
return;
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import java.util.List;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ShowBoard;
import javolution.util.FastList;
public abstract class BaseBBSManager
{
public abstract void parsecmd(String command, L2PcInstance activeChar);
public abstract void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar);
protected void separateAndSend(String html, L2PcInstance acha)
{
if (html == null)
{
return;
}
if (html.length() < 8180)
{
acha.sendPacket(new ShowBoard(html, "101"));
acha.sendPacket(new ShowBoard(null, "102"));
acha.sendPacket(new ShowBoard(null, "103"));
}
else if (html.length() < 16360)
{
acha.sendPacket(new ShowBoard(html.substring(0, 8180), "101"));
acha.sendPacket(new ShowBoard(html.substring(8180, html.length()), "102"));
acha.sendPacket(new ShowBoard(null, "103"));
}
else if (html.length() < 24540)
{
acha.sendPacket(new ShowBoard(html.substring(0, 8180), "101"));
acha.sendPacket(new ShowBoard(html.substring(8180, 16360), "102"));
acha.sendPacket(new ShowBoard(html.substring(16360, html.length()), "103"));
}
}
/**
* @param html
* @param acha
*/
protected void send1001(String html, L2PcInstance acha)
{
if (html.length() < 8180)
{
acha.sendPacket(new ShowBoard(html, "1001"));
}
}
/**
* @param acha
*/
protected void send1002(L2PcInstance acha)
{
send1002(acha, " ", " ", "0");
}
/**
* @param activeChar
* @param string
* @param string2
* @param string3
*/
protected void send1002(L2PcInstance activeChar, String string, String string2, String string3)
{
final List<String> _arg = new FastList<>();
_arg.add("0");
_arg.add("0");
_arg.add("0");
_arg.add("0");
_arg.add("0");
_arg.add("0");
_arg.add(activeChar.getName());
_arg.add(Integer.toString(activeChar.getObjectId()));
_arg.add(activeChar.getAccountName());
_arg.add("9");
_arg.add(string2);
_arg.add(string2);
_arg.add(string);
_arg.add(string3);
_arg.add(string3);
_arg.add("0");
_arg.add("0");
activeChar.sendPacket(new ShowBoard(_arg));
}
}

View File

@@ -0,0 +1,328 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import java.util.StringTokenizer;
import com.l2jmobius.gameserver.datatables.ClanTable;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import javolution.text.TextBuilder;
public class ClanBBSManager extends BaseBBSManager
{
private static ClanBBSManager _Instance = new ClanBBSManager();
/**
* @return
*/
public static ClanBBSManager getInstance()
{
return _Instance;
}
/**
* @param command
* @param activeChar
*/
@Override
public void parsecmd(String command, L2PcInstance activeChar)
{
if (command.equals("_bbsclan"))
{
if (activeChar.getClan() != null)
{
if (activeChar.getClan().getLevel() >= 2)
{
clanhome(activeChar);
}
else
{
clanlist(activeChar, 1);
}
}
else
{
clanlist(activeChar, 1);
}
}
else if (command.startsWith("_bbsclan_clanlist"))
{
if (command.equals("_bbsclan_clanlist"))
{
clanlist(activeChar, 1);
}
else if (command.startsWith("_bbsclan_clanlist;"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
final int index = Integer.parseInt(st.nextToken());
clanlist(activeChar, index);
}
}
else if (command.startsWith("_bbsclan_clanhome"))
{
if (command.equals("_bbsclan_clanhome"))
{
clanhome(activeChar);
}
else if (command.startsWith("_bbsclan_clanhome;"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
final int index = Integer.parseInt(st.nextToken());
clanhome(activeChar, index);
}
}
else
{
separateAndSend("<html><body><br><br><center>Command : " + command + " is not implemented yet</center><br><br></body></html>", activeChar);
}
}
/**
* @param activeChar
* @param index
*/
private void clanlist(L2PcInstance activeChar, int index)
{
if (index < 1)
{
index = 1;
}
// header
final TextBuilder html = new TextBuilder("<html><body><br><br><center>");
html.append("<br1><br1><table border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td FIXWIDTH=15>&nbsp;</td>");
html.append("<td width=610 height=30 align=left>");
html.append("<a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a>");
html.append("</td></tr></table>");
html.append("<table border=0 cellspacing=0 cellpadding=0 width=610 bgcolor=434343>");
html.append("<tr><td height=10></td></tr>");
html.append("<tr>");
html.append("<td fixWIDTH=5></td>");
html.append("<td fixWIDTH=600>");
html.append("<a action=\"bypass _bbsclan_clanhome;" + ((activeChar.getClan() != null) ? activeChar.getClan().getClanId() : 0) + "\">[GO TO MY CLAN]</a>&nbsp;&nbsp;");
html.append("</td>");
html.append("<td fixWIDTH=5></td>");
html.append("</tr>");
html.append("<tr><td height=10></td></tr>");
html.append("</table>");
// body
html.append("<br>");
html.append("<table border=0 cellspacing=0 cellpadding=2 bgcolor=5A5A5A width=610>");
html.append("<tr>");
html.append("<td FIXWIDTH=5></td>");
html.append("<td FIXWIDTH=200 align=center>CLAN NAME</td>");
html.append("<td FIXWIDTH=200 align=center>CLAN LEADER</td>");
html.append("<td FIXWIDTH=100 align=center>CLAN LEVEL</td>");
html.append("<td FIXWIDTH=100 align=center>CLAN MEMBERS</td>");
html.append("<td FIXWIDTH=5></td>");
html.append("</tr>");
html.append("</table>");
html.append("<img src=\"L2UI.Squareblank\" width=\"1\" height=\"5\">");
int i = 0;
for (final L2Clan cl : ClanTable.getInstance().getClans())
{
if (i > ((index + 1) * 7))
{
break;
}
if (i++ >= ((index - 1) * 7))
{
html.append("<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"3\">");
html.append("<table border=0 cellspacing=0 cellpadding=0 width=610>");
html.append("<tr> ");
html.append("<td FIXWIDTH=5></td>");
html.append("<td FIXWIDTH=200 align=center><a action=\"bypass _bbsclan_clanhome;" + cl.getClanId() + "\">" + cl.getName() + "</a></td>");
html.append("<td FIXWIDTH=200 align=center>" + cl.getLeaderName() + "</td>");
html.append("<td FIXWIDTH=100 align=center>" + cl.getLevel() + "</td>");
html.append("<td FIXWIDTH=100 align=center>" + cl.getMembersCount() + "</td>");
html.append("<td FIXWIDTH=5></td>");
html.append("</tr>");
html.append("<tr><td height=5></td></tr>");
html.append("</table>");
html.append("<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"3\">");
html.append("<img src=\"L2UI.SquareGray\" width=\"610\" height=\"1\">");
}
}
html.append("<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"2\">");
html.append("<table cellpadding=0 cellspacing=2 border=0><tr>");
if (index == 1)
{
html.append("<td><button action=\"\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
}
else
{
html.append("<td><button action=\"_bbsclan_clanlist;" + (index - 1) + "\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
}
i = 0;
int nbp;
nbp = ClanTable.getInstance().getClans().length / 8;
if ((nbp * 8) != ClanTable.getInstance().getClans().length)
{
nbp++;
}
for (i = 1; i <= nbp; i++)
{
if (i == index)
{
html.append("<td> " + i + " </td>");
}
else
{
html.append("<td><a action=\"bypass _bbsclan_clanlist;" + i + "\"> " + i + " </a></td>");
}
}
if (index == nbp)
{
html.append("<td><button action=\"\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
}
else
{
html.append("<td><button action=\"bypass _bbsclan_clanlist;" + (index + 1) + "\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
}
html.append("</tr></table>");
html.append("<table border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td width=610><img src=\"sek.cbui141\" width=\"610\" height=\"1\"></td></tr>");
html.append("</table>");
html.append("<table border=0><tr><td><combobox width=65 var=keyword list=\"Name;Ruler\"></td><td><edit var = \"Search\" width=130 height=11 length=\"16\"></td>");
// TODO: search (Write in BBS)
html.append("<td><button value=\"&$420;\" action=\"Write 5 -1 0 Search keyword keyword\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td> </tr></table>");
html.append("<br>");
html.append("<br>");
html.append("</center>");
html.append("</body>");
html.append("</html>");
separateAndSend(html.toString(), activeChar);
}
/**
* @param activeChar
*/
private void clanhome(L2PcInstance activeChar)
{
clanhome(activeChar, activeChar.getClan().getClanId());
}
/**
* @param activeChar
* @param clanId
*/
private void clanhome(L2PcInstance activeChar, int clanId)
{
final L2Clan cl = ClanTable.getInstance().getClan(clanId);
if (cl != null)
{
if (cl.getLevel() < 2)
{
activeChar.sendPacket(new SystemMessage(SystemMessage.NO_CB_IN_MY_CLAN));
parsecmd("_bbsclan_clanlist", activeChar);
}
else
{
final TextBuilder html = new TextBuilder("<html><body><center><br><br>");
html.append("<br1><br1><table border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td FIXWIDTH=15>&nbsp;</td>");
html.append("<td width=610 height=30 align=left>");
html.append("<a action=\"bypass _bbshome\">HOME</a> &gt; <a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a> &gt; <a action=\"bypass _bbsclan_clanhome;" + clanId + "\"> &amp;$802; </a>");
html.append("</td></tr></table>");
html.append("<table border=0 cellspacing=0 cellpadding=0 width=610 bgcolor=434343>");
html.append("<tr><td height=10></td></tr>");
html.append("<tr>");
html.append("<td fixWIDTH=5></td>");
html.append("<td fixwidth=600>");
html.append("<a action=\"bypass _bbsclan_clanhome;" + clanId + ";announce\">[CLAN ANNOUNCEMENT]</a> <a action=\"bypass _bbsclan_clanhome;" + clanId + ";cbb\">[CLAN BULLETIN BOARD]</a>");
html.append("<a action=\"bypass _bbsclan_clanhome;" + clanId + ";cmail\">[CLAN MAIL]</a>&nbsp;&nbsp;");
html.append("<a action=\"bypass _bbsclan_clanhome;" + clanId + ";cnotice\">[CLAN NOTICE]</a>&nbsp;&nbsp;");
html.append("</td>");
html.append("<td fixWIDTH=5></td>");
html.append("</tr>");
html.append("<tr><td height=10></td></tr>");
html.append("</table>");
html.append("<table border=0 cellspacing=0 cellpadding=0 width=610>");
html.append("<tr><td height=10></td></tr>");
html.append("<tr><td fixWIDTH=5></td>");
html.append("<td fixwidth=290 valign=top>");
html.append("</td>");
html.append("<td fixWIDTH=5></td>");
html.append("<td fixWIDTH=5 align=center valign=top><img src=\"l2ui.squaregray\" width=2 height=128></td>");
html.append("<td fixWIDTH=5></td>");
html.append("<td fixwidth=295>");
html.append("<table border=0 cellspacing=0 cellpadding=0 width=295>");
html.append("<tr>");
html.append("<td fixWIDTH=100 align=left>CLAN NAME</td>");
html.append("<td fixWIDTH=195 align=left>" + cl.getName() + "</td>");
html.append("</tr>");
html.append("<tr><td height=7></td></tr>");
html.append("<tr>");
html.append("<td fixWIDTH=100 align=left>CLAN LEVEL</td>");
html.append("<td fixWIDTH=195 align=left height=16>" + cl.getLevel() + "</td>");
html.append("</tr>");
html.append("<tr><td height=7></td></tr>");
html.append("<tr>");
html.append("<td fixWIDTH=100 align=left>CLAN MEMBERS</td>");
html.append("<td fixWIDTH=195 align=left height=16>" + cl.getMembersCount() + "</td>");
html.append("</tr>");
html.append("<tr><td height=7></td></tr>");
html.append("<tr>");
html.append("<td fixWIDTH=100 align=left>CLAN LEADER</td>");
html.append("<td fixWIDTH=195 align=left height=16>" + cl.getLeaderName() + "</td>");
html.append("</tr>");
html.append("<tr><td height=7></td></tr>");
// ADMINISTRATOR ??
/*
* html.append("<tr>"); html.append("<td fixWIDTH=100 align=left>ADMINISTRATOR</td>"); html.append("<td fixWIDTH=195 align=left height=16>"+cl.getLeaderName()+"</td>"); html.append("</tr>");
*/
html.append("<tr><td height=7></td></tr>");
html.append("<tr>");
html.append("<td fixWIDTH=100 align=left>ALLIANCE</td>");
html.append("<td fixWIDTH=195 align=left height=16>" + ((cl.getAllyName() != null) ? cl.getAllyName() : "") + "</td>");
html.append("</tr>");
html.append("</table>");
html.append("</td>");
html.append("<td fixWIDTH=5></td>");
html.append("</tr>");
html.append("<tr><td height=10></td></tr>");
html.append("</table>");
// TODO: the BB for clan :)
// html.append("<table border=0 cellspacing=0 cellpadding=0 width=610 bgcolor=333333>");
html.append("<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">");
html.append("<img src=\"L2UI.squaregray\" width=\"610\" height=\"1\">");
html.append("<br>");
html.append("</center>");
html.append("<br> <br>");
html.append("</body>");
html.append("</html>");
separateAndSend(html.toString(), activeChar);
}
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsewrite(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
{
// TODO Auto-generated method stub
}
}

View File

@@ -0,0 +1,170 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.communitybbs.BB.Forum;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import javolution.util.FastList;
public class ForumsBBSManager extends BaseBBSManager
{
private static Logger _log = Logger.getLogger(ForumsBBSManager.class.getName());
private final List<Forum> _table;
private static ForumsBBSManager _Instance;
private int lastid = 1;
/**
* @return
*/
public static ForumsBBSManager getInstance()
{
if (_Instance == null)
{
_Instance = new ForumsBBSManager();
}
return _Instance;
}
public ForumsBBSManager()
{
_table = new FastList<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT forum_id FROM forums WHERE forum_type=0");
ResultSet result = statement.executeQuery())
{
while (result.next())
{
final int forumId = result.getInt("forum_id");
final Forum f = new Forum(forumId, null);
addForum(f);
}
}
catch (final Exception e)
{
_log.warning("data error on Forum (root): " + e);
e.printStackTrace();
}
}
public void initRoot()
{
for (final Forum f : _table)
{
f.vload();
}
_log.info("Loaded " + _table.size() + " forums. Last forum id used: " + lastid);
}
public void addForum(Forum ff)
{
if (ff == null)
{
return;
}
_table.add(ff);
if (ff.getID() > lastid)
{
lastid = ff.getID();
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsecmd(String command, L2PcInstance activeChar)
{
// TODO Auto-generated method stub
}
/**
* @param Name
* @return
*/
public Forum getForumByName(String Name)
{
for (final Forum f : _table)
{
if (f.getName().equals(Name))
{
return f;
}
}
return null;
}
/**
* @param name
* @param parent
* @param type
* @param perm
* @param oid
* @return
*/
public Forum CreateNewForum(String name, Forum parent, int type, int perm, int oid)
{
final Forum forum = new Forum(name, parent, type, perm, oid);
forum.insertindb();
return forum;
}
/**
* @return
*/
public int GetANewID()
{
return ++lastid;
}
/**
* @param idf
* @return
*/
public Forum getForumByID(int idf)
{
for (final Forum f : _table)
{
if (f.getID() == idf)
{
return f;
}
}
return null;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsewrite(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
{
// TODO Auto-generated method stub
}
}

View File

@@ -0,0 +1,374 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import com.l2jmobius.gameserver.communitybbs.BB.Forum;
import com.l2jmobius.gameserver.communitybbs.BB.Post;
import com.l2jmobius.gameserver.communitybbs.BB.Post.CPost;
import com.l2jmobius.gameserver.communitybbs.BB.Topic;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ShowBoard;
import javolution.text.TextBuilder;
import javolution.util.FastMap;
public class PostBBSManager extends BaseBBSManager
{
private final Map<Topic, Post> _PostByTopic;
private static PostBBSManager _Instance;
public static PostBBSManager getInstance()
{
if (_Instance == null)
{
_Instance = new PostBBSManager();
}
return _Instance;
}
public PostBBSManager()
{
_PostByTopic = new FastMap<>();
}
public Post getGPosttByTopic(Topic t)
{
Post post = null;
post = _PostByTopic.get(t);
if (post == null)
{
post = load(t);
_PostByTopic.put(t, post);
}
return post;
}
/**
* @param t
*/
public void delPostByTopic(Topic t)
{
_PostByTopic.remove(t);
}
public void addPostByTopic(Post p, Topic t)
{
if (_PostByTopic.get(t) == null)
{
_PostByTopic.put(t, p);
}
}
/**
* @param t
* @return
*/
private Post load(Topic t)
{
Post p;
p = new Post(t);
return p;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsecmd(String command, L2PcInstance activeChar)
{
if (command.startsWith("_bbsposts;read;"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
st.nextToken();
final int idf = Integer.parseInt(st.nextToken());
final int idp = Integer.parseInt(st.nextToken());
String index = null;
if (st.hasMoreTokens())
{
index = st.nextToken();
}
int ind = 0;
if (index == null)
{
ind = 1;
}
else
{
ind = Integer.parseInt(index);
}
showPost((TopicBBSManager.getInstance().getTopicByID(idp)), ForumsBBSManager.getInstance().getForumByID(idf), activeChar, ind);
}
else if (command.startsWith("_bbsposts;edit;"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
st.nextToken();
final int idf = Integer.parseInt(st.nextToken());
final int idt = Integer.parseInt(st.nextToken());
final int idp = Integer.parseInt(st.nextToken());
showEditPost((TopicBBSManager.getInstance().getTopicByID(idt)), ForumsBBSManager.getInstance().getForumByID(idf), activeChar, idp);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/**
* @param topic
* @param forum
* @param activeChar
* @param idp
*/
private void showEditPost(Topic topic, Forum forum, L2PcInstance activeChar, int idp)
{
final Post p = getGPosttByTopic(topic);
if ((forum == null) || (topic == null) || (p == null))
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>Error, this forum, topic or post does not exit !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
ShowHtmlEditPost(topic, activeChar, forum, p);
}
}
/**
* @param topic
* @param forum
* @param activeChar
* @param ind
*/
private void showPost(Topic topic, Forum forum, L2PcInstance activeChar, int ind)
{
if ((forum == null) || (topic == null))
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>Error, this forum is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else if (forum.getType() == Forum.MEMO)
{
ShowMemoPost(topic, activeChar, forum);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName() + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/**
* @param topic
* @param activeChar
* @param forum
* @param p
*/
private void ShowHtmlEditPost(Topic topic, L2PcInstance activeChar, Forum forum, Post p)
{
final TextBuilder html = new TextBuilder("<html>");
html.append("<body><br><br>");
html.append("<table border=0 width=610><tr><td width=10></td><td width=600 align=left>");
html.append("<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">" + forum.getName() + " Form</a>");
html.append("</td></tr>");
html.append("</table>");
html.append("<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");
html.append("<center>");
html.append("<table border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td width=610><img src=\"sek.cbui355\" width=\"610\" height=\"1\"><br1><img src=\"sek.cbui355\" width=\"610\" height=\"1\"></td></tr>");
html.append("</table>");
html.append("<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=20></td></tr>");
html.append("<tr>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("<td align=center FIXWIDTH=60 height=29>&$413;</td>");
html.append("<td FIXWIDTH=540>" + topic.getName() + "</td>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("</tr></table>");
html.append("<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>");
html.append("<tr>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("<td align=center FIXWIDTH=60 height=29 valign=top>&$427;</td>");
html.append("<td align=center FIXWIDTH=540><MultiEdit var =\"Content\" width=535 height=313></td>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("</tr>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>");
html.append("</table>");
html.append("<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>");
html.append("<tr>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("<td align=center FIXWIDTH=60 height=29>&nbsp;</td>");
html.append("<td align=center FIXWIDTH=70><button value=\"&$140;\" action=\"Write Post " + forum.getID() + ";" + topic.getID() + ";0 _ Content Content Content\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>");
html.append("<td align=center FIXWIDTH=70><button value = \"&$141;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td>");
html.append("<td align=center FIXWIDTH=400>&nbsp;</td>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("</tr></table>");
html.append("</center>");
html.append("</body>");
html.append("</html>");
send1001(html.toString(), activeChar);
send1002(activeChar, p.getCPost(0)._PostTxt, topic.getName(), DateFormat.getInstance().format(new Date(topic.getDate())));
}
/**
* @param topic
* @param activeChar
* @param forum
*/
private void ShowMemoPost(Topic topic, L2PcInstance activeChar, Forum forum)
{
//
final Post p = getGPosttByTopic(topic);
final Locale locale = Locale.getDefault();
final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL, locale);
final TextBuilder html = new TextBuilder("<html><body><br><br>");
html.append("<table border=0 width=610><tr><td width=10></td><td width=600 align=left>");
html.append("<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>");
html.append("</td></tr>");
html.append("</table>");
html.append("<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");
html.append("<center>");
html.append("<table border=0 cellspacing=0 cellpadding=0 bgcolor=333333>");
html.append("<tr><td height=10></td></tr>");
html.append("<tr>");
html.append("<td fixWIDTH=55 align=right valign=top>&$413; : &nbsp;</td>");
html.append("<td fixWIDTH=380 valign=top>" + topic.getName() + "</td>");
html.append("<td fixwidth=5></td>");
html.append("<td fixwidth=50></td>");
html.append("<td fixWIDTH=120></td>");
html.append("</tr>");
html.append("<tr><td height=10></td></tr>");
html.append("<tr>");
html.append("<td align=right><font color=\"AAAAAA\" >&$417; : &nbsp;</font></td>");
html.append("<td><font color=\"AAAAAA\">" + topic.getOwnerName() + "</font></td>");
html.append("<td></td>");
html.append("<td><font color=\"AAAAAA\">&$418; :</font></td>");
html.append("<td><font color=\"AAAAAA\">" + dateFormat.format(p.getCPost(0)._PostDate) + "</font></td>");
html.append("</tr>");
html.append("<tr><td height=10></td></tr>");
html.append("</table>");
html.append("<br>");
html.append("<table border=0 cellspacing=0 cellpadding=0>");
html.append("<tr>");
html.append("<td fixwidth=5></td>");
String Mes = p.getCPost(0)._PostTxt.replace(">", "&gt;");
Mes = Mes.replace("<", "&lt;");
Mes = Mes.replace("\n", "<br1>");
html.append("<td FIXWIDTH=600 align=left>" + Mes + "</td>");
html.append("<td fixqqwidth=5></td>");
html.append("</tr>");
html.append("</table>");
html.append("<br>");
html.append("<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">");
html.append("<img src=\"L2UI.squaregray\" width=\"610\" height=\"1\">");
html.append("<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">");
html.append("<table border=0 cellspacing=0 cellpadding=0 FIXWIDTH=610>");
html.append("<tr>");
html.append("<td width=50>");
html.append("<button value=\"&$422;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\">");
html.append("</td>");
html.append("<td width=560 align=right><table border=0 cellspacing=0><tr>");
html.append("<td FIXWIDTH=300></td><td><button value = \"&$424;\" action=\"bypass _bbsposts;edit;" + forum.getID() + ";" + topic.getID() + ";0\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;");
html.append("<td><button value = \"&$425;\" action=\"bypass _bbstopics;del;" + forum.getID() + ";" + topic.getID() + "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;");
html.append("<td><button value = \"&$421;\" action=\"bypass _bbstopics;crea;" + forum.getID() + "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;");
html.append("</tr></table>");
html.append("</td>");
html.append("</tr>");
html.append("</table>");
html.append("<br>");
html.append("<br>");
html.append("<br></center>");
html.append("</body>");
html.append("</html>");
separateAndSend(html.toString(), activeChar);
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsewrite(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
{
final StringTokenizer st = new StringTokenizer(ar1, ";");
final int idf = Integer.parseInt(st.nextToken());
final int idt = Integer.parseInt(st.nextToken());
final int idp = Integer.parseInt(st.nextToken());
final Forum f = ForumsBBSManager.getInstance().getForumByID(idf);
if (f == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " does not exist !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
final Topic t = f.gettopic(idt);
if (t == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + idt + " does not exist !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
CPost cp = null;
final Post p = getGPosttByTopic(t);
if (p != null)
{
cp = p.getCPost(idp);
}
if (cp == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the post: " + idp + " does not exist !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else if (p != null)
{
p.getCPost(idp)._PostTxt = ar4;
p.updatetxt(idp);
parsecmd("_bbsposts;read;" + f.getID() + ";" + t.getID(), activeChar);
}
}
}
}
}

View File

@@ -0,0 +1,680 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import java.util.Collection;
import java.util.Collections;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.GameServer;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.base.Experience;
import com.l2jmobius.gameserver.network.clientpackets.Say2;
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import com.l2jmobius.gameserver.network.serverpackets.ShowBoard;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import javolution.text.TextBuilder;
import javolution.util.FastList;
import javolution.util.FastMap;
public class RegionBBSManager extends BaseBBSManager
{
private static Logger _logChat = Logger.getLogger("chat");
private static RegionBBSManager _Instance = null;
private int _onlineCount = 0;
private int _onlineCountGm = 0;
private static FastMap<Integer, FastList<L2PcInstance>> _onlinePlayers = new FastMap<Integer, FastList<L2PcInstance>>().shared();
private static FastMap<Integer, FastMap<String, String>> _communityPages = new FastMap<Integer, FastMap<String, String>>().shared();
/**
* @return
*/
public static RegionBBSManager getInstance()
{
if (_Instance == null)
{
_Instance = new RegionBBSManager();
}
return _Instance;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsecmd(String command, L2PcInstance activeChar)
{
if (command.equals("_bbsloc"))
{
showOldCommunity(activeChar, 1);
}
else if (command.startsWith("_bbsloc;page;"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
st.nextToken();
int page = 0;
try
{
page = Integer.parseInt(st.nextToken());
}
catch (final NumberFormatException nfe)
{
}
showOldCommunity(activeChar, page);
}
else if (command.startsWith("_bbsloc;playerinfo;"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
st.nextToken();
final String name = st.nextToken();
showOldCommunityPI(activeChar, name);
}
else
{
if (Config.COMMUNITY_TYPE == 1)
{
showOldCommunity(activeChar, 1);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
}
/**
* @param activeChar
* @param name
*/
private void showOldCommunityPI(L2PcInstance activeChar, String name)
{
final TextBuilder htmlCode = new TextBuilder("<html><body><br>");
htmlCode.append("<table border=0><tr><td FIXWIDTH=15></td><td align=center>Community Board<img src=\"sek.cbui355\" width=610 height=1></td></tr><tr><td FIXWIDTH=15></td><td>");
final L2PcInstance player = L2World.getInstance().getPlayer(name);
if (player != null)
{
String sex = "Male";
if (player.getAppearance().getSex())
{
sex = "Female";
}
String levelApprox = "low";
if (player.getLevel() >= 60)
{
levelApprox = "very high";
}
else if (player.getLevel() >= 40)
{
levelApprox = "high";
}
else if (player.getLevel() >= 20)
{
levelApprox = "medium";
}
htmlCode.append("<table border=0><tr><td>" + player.getName() + " (" + sex + " " + player.getTemplate().className + "):</td></tr>");
htmlCode.append("<tr><td>Level: " + levelApprox + "</td></tr>");
htmlCode.append("<tr><td><br></td></tr>");
if ((activeChar != null) && (activeChar.isGM() || (player.getObjectId() == activeChar.getObjectId()) || Config.SHOW_LEVEL_COMMUNITYBOARD))
{
long nextLevelExp = 0;
long nextLevelExpNeeded = 0;
if (player.getLevel() < (Experience.MAX_LEVEL - 1))
{
nextLevelExp = Experience.LEVEL[player.getLevel() + 1];
nextLevelExpNeeded = nextLevelExp - player.getExp();
}
htmlCode.append("<tr><td>Level: " + player.getLevel() + "</td></tr>");
htmlCode.append("<tr><td>Experience: " + player.getExp() + "/" + nextLevelExp + "</td></tr>");
htmlCode.append("<tr><td>Experience needed for level up: " + nextLevelExpNeeded + "</td></tr>");
htmlCode.append("<tr><td><br></td></tr>");
}
final int uptime = (int) player.getUptime() / 1000;
final int h = uptime / 3600;
final int m = (uptime - (h * 3600)) / 60;
final int s = ((uptime - (h * 3600)) - (m * 60));
htmlCode.append("<tr><td>Uptime: " + h + "h " + m + "m " + s + "s</td></tr>");
htmlCode.append("<tr><td><br></td></tr>");
if (player.getClan() != null)
{
htmlCode.append("<tr><td>Clan: " + player.getClan().getName() + "</td></tr>");
htmlCode.append("<tr><td><br></td></tr>");
}
htmlCode.append("<tr><td><multiedit var=\"pm\" width=240 height=40><button value=\"Send PM\" action=\"Write Region PM " + player.getName() + " pm pm pm\" width=110 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr><tr><td><br><button value=\"Back\" action=\"bypass _bbsloc\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td></tr></table>");
htmlCode.append("</td></tr></table>");
htmlCode.append("</body></html>");
separateAndSend(htmlCode.toString(), activeChar);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>No player with name " + name + "</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/**
* @param activeChar
* @param page
*/
private void showOldCommunity(L2PcInstance activeChar, int page)
{
separateAndSend(getCommunityPage(page, activeChar.isGM() ? "gm" : "pl"), activeChar);
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsewrite(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
{
if (activeChar == null)
{
return;
}
if (ar1.equals("PM"))
{
final TextBuilder htmlCode = new TextBuilder("<html><body><br>");
htmlCode.append("<table border=0><tr><td FIXWIDTH=15></td><td align=center>Community Board<img src=\"sek.cbui355\" width=610 height=1></td></tr><tr><td FIXWIDTH=15></td><td>");
try
{
final L2PcInstance receiver = L2World.getInstance().getPlayer(ar2);
if (receiver == null)
{
htmlCode.append("Player not found!<br><button value=\"Back\" action=\"bypass _bbsloc;playerinfo;" + ar2 + "\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\">");
htmlCode.append("</td></tr></table></body></html>");
separateAndSend(htmlCode.toString(), activeChar);
return;
}
if (Config.JAIL_DISABLE_CHAT && receiver.isInJail())
{
activeChar.sendMessage("Player is in jail.");
return;
}
if (receiver.isChatBanned())
{
activeChar.sendMessage("Player is chat-banned.");
return;
}
if (activeChar.isInJail() && Config.JAIL_DISABLE_CHAT)
{
activeChar.sendMessage("You cannot chat while in jail.");
return;
}
if (Config.LOG_CHAT)
{
final LogRecord record = new LogRecord(Level.INFO, ar3);
record.setLoggerName("chat");
record.setParameters(new Object[]
{
"TELL",
"[" + activeChar.getName() + " to " + receiver.getName() + "]"
});
_logChat.log(record);
}
final CreatureSay cs = new CreatureSay(activeChar.getObjectId(), Say2.TELL, activeChar.getName(), ar3);
if (!BlockList.isBlocked(receiver, activeChar))
{
if (!receiver.getMessageRefusal())
{
receiver.sendPacket(cs);
activeChar.sendPacket(new CreatureSay(activeChar.getObjectId(), Say2.TELL, "->" + receiver.getName(), ar3));
htmlCode.append("Message Sent<br><button value=\"Back\" action=\"bypass _bbsloc;playerinfo;" + receiver.getName() + "\" width=40 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\">");
htmlCode.append("</td></tr></table></body></html>");
separateAndSend(htmlCode.toString(), activeChar);
}
else
{
final SystemMessage sm = new SystemMessage(SystemMessage.THE_PERSON_IS_IN_MESSAGE_REFUSAL_MODE);
activeChar.sendPacket(sm);
parsecmd("_bbsloc;playerinfo;" + receiver.getName(), activeChar);
}
}
else
{
SystemMessage sm = new SystemMessage(SystemMessage.S1_IS_NOT_ONLINE);
sm.addString(receiver.getName());
activeChar.sendPacket(sm);
sm = null;
}
}
catch (final StringIndexOutOfBoundsException e)
{
// ignore
}
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + ar1 + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
public synchronized void changeCommunityBoard()
{
if (Config.COMMUNITY_TYPE == 0)
{
return;
}
Collection<L2PcInstance> players = L2World.getInstance().getAllPlayers();
final FastList<L2PcInstance> sortedPlayers = new FastList<>();
sortedPlayers.addAll(players);
players = null;
Collections.sort(sortedPlayers, (p1, p2) -> p1.getName().compareToIgnoreCase(p2.getName()));
_onlinePlayers.clear();
_onlineCount = 0;
_onlineCountGm = 0;
for (final L2PcInstance player : sortedPlayers)
{
addOnlinePlayer(player);
}
_communityPages.clear();
writeCommunityPages();
}
private void addOnlinePlayer(L2PcInstance player)
{
boolean added = false;
for (final FastList<L2PcInstance> page : _onlinePlayers.values())
{
if (page.size() < Config.NAME_PAGE_SIZE_COMMUNITYBOARD)
{
if (!page.contains(player))
{
page.add(player);
if (!player.getAppearance().getInvisible())
{
_onlineCount++;
}
_onlineCountGm++;
}
added = true;
break;
}
else if (page.contains(player))
{
added = true;
break;
}
}
if (!added)
{
final FastList<L2PcInstance> temp = new FastList<>();
final int page = _onlinePlayers.size() + 1;
if (temp.add(player))
{
_onlinePlayers.put(page, temp);
if (!player.getAppearance().getInvisible())
{
_onlineCount++;
}
_onlineCountGm++;
}
}
}
private void writeCommunityPages()
{
for (final int page : _onlinePlayers.keySet())
{
final FastMap<String, String> communityPage = new FastMap<>();
TextBuilder htmlCode = new TextBuilder("<html><body><br>");
final String tdClose = "</td>";
final String tdOpen = "<td align=left valign=top>";
final String trClose = "</tr>";
final String trOpen = "<tr>";
final String colSpacer = "<td FIXWIDTH=15></td>";
htmlCode.append("<table>");
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "Server Restarted: " + GameServer.DateTimeServerStarted.getTime() + tdClose);
htmlCode.append(trClose);
htmlCode.append("</table>");
htmlCode.append("<table>");
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "XP Rate: x" + Config.RATE_XP + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Party XP Rate: x" + (Config.RATE_XP * Config.RATE_PARTY_XP) + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "XP Exponent: " + Config.ALT_GAME_EXPONENT_XP + tdClose);
htmlCode.append(trClose);
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "SP Rate: x" + Config.RATE_SP + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Party SP Rate: x" + (Config.RATE_SP * Config.RATE_PARTY_SP) + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "SP Exponent: " + Config.ALT_GAME_EXPONENT_SP + tdClose);
htmlCode.append(trClose);
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "Drop Rate: x" + Config.RATE_DROP_ITEMS + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Boss Drop Rate: x" + Config.RATE_BOSS_DROP_ITEMS + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Spoil Rate: x" + Config.RATE_DROP_SPOIL + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Adena Rate: x" + Config.RATE_DROP_ADENA + tdClose);
htmlCode.append(trClose);
htmlCode.append("</table>");
htmlCode.append("<table>");
htmlCode.append(trOpen);
htmlCode.append("<td><img src=\"sek.cbui355\" width=600 height=1><br></td>");
htmlCode.append(trClose);
htmlCode.append(trOpen);
htmlCode.append(tdOpen + L2World.getInstance().getAllVisibleObjectsCount() + " Object count</td>");
htmlCode.append(trClose);
htmlCode.append(trOpen);
htmlCode.append(tdOpen + getOnlineCount("gm") + " Player(s) Online</td>");
htmlCode.append(trClose);
htmlCode.append("</table>");
int cell = 0;
if (Config.BBS_SHOW_PLAYERLIST)
{
htmlCode.append("<table border=0>");
htmlCode.append("<tr><td><table border=0>");
for (final L2PcInstance player : getOnlinePlayers(page))
{
cell++;
if (cell == 1)
{
htmlCode.append(trOpen);
}
htmlCode.append("<td align=left valign=top FIXWIDTH=110><a action=\"bypass _bbsloc;playerinfo;" + player.getName() + "\">");
if (player.isGM())
{
htmlCode.append("<font color=\"LEVEL\">" + player.getName() + "</font>");
}
else
{
htmlCode.append(player.getName());
}
htmlCode.append("</a></td>");
if (cell < Config.NAME_PER_ROW_COMMUNITYBOARD)
{
htmlCode.append(colSpacer);
}
if (cell == Config.NAME_PER_ROW_COMMUNITYBOARD)
{
cell = 0;
htmlCode.append(trClose);
}
}
if ((cell > 0) && (cell < Config.NAME_PER_ROW_COMMUNITYBOARD))
{
htmlCode.append(trClose);
}
htmlCode.append("</table></td></tr>");
htmlCode.append(trOpen);
htmlCode.append("<td><img src=\"sek.cbui355\" width=600 height=1><br></td>");
htmlCode.append(trClose);
htmlCode.append("</table>");
}
if (getOnlineCount("gm") > Config.NAME_PAGE_SIZE_COMMUNITYBOARD)
{
htmlCode.append("<table border=0 width=600>");
htmlCode.append("<tr>");
if (page == 1)
{
htmlCode.append("<td align=right width=190><button value=\"Prev\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
else
{
htmlCode.append("<td align=right width=190><button value=\"Prev\" action=\"bypass _bbsloc;page;" + (page - 1) + "\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
htmlCode.append("<td FIXWIDTH=10></td>");
htmlCode.append("<td align=center valign=top width=200>Displaying " + (((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + 1) + " - " + (((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + getOnlinePlayers(page).size()) + " player(s)</td>");
htmlCode.append("<td FIXWIDTH=10></td>");
if (getOnlineCount("gm") <= (page * Config.NAME_PAGE_SIZE_COMMUNITYBOARD))
{
htmlCode.append("<td width=190><button value=\"Next\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
else
{
htmlCode.append("<td width=190><button value=\"Next\" action=\"bypass _bbsloc;page;" + (page + 1) + "\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
htmlCode.append("</tr>");
htmlCode.append("</table>");
}
htmlCode.append("</body></html>");
communityPage.put("gm", htmlCode.toString());
htmlCode = new TextBuilder("<html><body><br>");
htmlCode.append("<table>");
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "Server Restarted: " + GameServer.DateTimeServerStarted.getTime() + tdClose);
htmlCode.append(trClose);
htmlCode.append("</table>");
htmlCode.append("<table>");
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "XP Rate: x" + Config.RATE_XP + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Party XP Rate: x" + (Config.RATE_XP * Config.RATE_PARTY_XP) + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "XP Exponent: " + Config.ALT_GAME_EXPONENT_XP + tdClose);
htmlCode.append(trClose);
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "SP Rate: x" + Config.RATE_SP + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Party SP Rate: x" + (Config.RATE_SP * Config.RATE_PARTY_SP) + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "SP Exponent: " + Config.ALT_GAME_EXPONENT_SP + tdClose);
htmlCode.append(trClose);
htmlCode.append(trOpen);
htmlCode.append(tdOpen + "Drop Rate: x" + Config.RATE_DROP_ITEMS + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Boss Drop Rate: x" + Config.RATE_BOSS_DROP_ITEMS + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Spoil Rate: x" + Config.RATE_DROP_SPOIL + tdClose);
htmlCode.append(colSpacer);
htmlCode.append(tdOpen + "Adena Rate: x" + Config.RATE_DROP_ADENA + tdClose);
htmlCode.append(trClose);
htmlCode.append("</table>");
htmlCode.append("<table>");
htmlCode.append(trOpen);
htmlCode.append("<td><img src=\"sek.cbui355\" width=600 height=1><br></td>");
htmlCode.append(trClose);
htmlCode.append(trOpen);
htmlCode.append(tdOpen + getOnlineCount("gm") + " Player(s) Online</td>");
htmlCode.append(trClose);
htmlCode.append("</table>");
if (Config.BBS_SHOW_PLAYERLIST)
{
htmlCode.append("<table border=0>");
htmlCode.append("<tr><td><table border=0>");
cell = 0;
for (final L2PcInstance player : getOnlinePlayers(page))
{
if ((player == null) || player.getAppearance().getInvisible())
{
continue; // Go to next
}
cell++;
if (cell == 1)
{
htmlCode.append(trOpen);
}
htmlCode.append("<td align=left valign=top FIXWIDTH=110><a action=\"bypass _bbsloc;playerinfo;" + player.getName() + "\">");
if (player.isGM())
{
htmlCode.append("<font color=\"LEVEL\">" + player.getName() + "</font>");
}
else
{
htmlCode.append(player.getName());
}
htmlCode.append("</a></td>");
if (cell < Config.NAME_PER_ROW_COMMUNITYBOARD)
{
htmlCode.append(colSpacer);
}
if (cell == Config.NAME_PER_ROW_COMMUNITYBOARD)
{
cell = 0;
htmlCode.append(trClose);
}
}
if ((cell > 0) && (cell < Config.NAME_PER_ROW_COMMUNITYBOARD))
{
htmlCode.append(trClose);
}
htmlCode.append("</table><br></td></tr>");
htmlCode.append(trOpen);
htmlCode.append("<td><img src=\"sek.cbui355\" width=600 height=1><br></td>");
htmlCode.append(trClose);
htmlCode.append("</table>");
}
if (getOnlineCount("pl") > Config.NAME_PAGE_SIZE_COMMUNITYBOARD)
{
htmlCode.append("<table border=0 width=600>");
htmlCode.append("<tr>");
if (page == 1)
{
htmlCode.append("<td align=right width=190><button value=\"Prev\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
else
{
htmlCode.append("<td align=right width=190><button value=\"Prev\" action=\"bypass _bbsloc;page;" + (page - 1) + "\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
htmlCode.append("<td FIXWIDTH=10></td>");
htmlCode.append("<td align=center valign=top width=200>Displaying " + (((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + 1) + " - " + (((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + getOnlinePlayers(page).size()) + " player(s)</td>");
htmlCode.append("<td FIXWIDTH=10></td>");
if (getOnlineCount("pl") <= (page * Config.NAME_PAGE_SIZE_COMMUNITYBOARD))
{
htmlCode.append("<td width=190><button value=\"Next\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
else
{
htmlCode.append("<td width=190><button value=\"Next\" action=\"bypass _bbsloc;page;" + (page + 1) + "\" width=50 height=15 back=\"sek.cbui94\" fore=\"sek.cbui92\"></td>");
}
htmlCode.append("</tr>");
htmlCode.append("</table>");
}
htmlCode.append("</body></html>");
communityPage.put("pl", htmlCode.toString());
_communityPages.put(page, communityPage);
}
}
private int getOnlineCount(String type)
{
if (type.equalsIgnoreCase("gm"))
{
return _onlineCountGm;
}
return _onlineCount;
}
private FastList<L2PcInstance> getOnlinePlayers(int page)
{
return _onlinePlayers.get(page);
}
public String getCommunityPage(int page, String type)
{
if (_communityPages.get(page) != null)
{
return _communityPages.get(page).get(type);
}
return null;
}
}

View File

@@ -0,0 +1,92 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import java.util.StringTokenizer;
import com.l2jmobius.gameserver.cache.HtmCache;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ShowBoard;
public class TopBBSManager extends BaseBBSManager
{
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsecmd(String command, L2PcInstance activeChar)
{
if (command.equals("_bbstop"))
{
String content = HtmCache.getInstance().getHtm("data/html/CommunityBoard/index.htm");
if (content == null)
{
content = new String("<html><body><br><br><center>404 :File Not found: 'data/html/CommunityBoard/index.htm' </center></body></html>");
}
separateAndSend(content, activeChar);
}
else if (command.equals("_bbshome"))
{
String content = HtmCache.getInstance().getHtm("data/html/CommunityBoard/index.htm");
if (content == null)
{
content = new String("<html><body><br><br><center>404 :File Not found: 'data/html/CommunityBoard/index.htm' </center></body></html>");
}
separateAndSend(content, activeChar);
}
else if (command.startsWith("_bbstop;"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
final int idp = Integer.parseInt(st.nextToken());
String content = HtmCache.getInstance().getHtm("data/html/CommunityBoard/" + idp + ".htm");
if (content == null)
{
content = new String("<html><body><br><br><center>404 :File Not found: 'data/html/CommunityBoard/" + idp + ".htm' </center></body></html>");
}
separateAndSend(content, activeChar);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsewrite(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
{
// TODO Auto-generated method stub
}
private static TopBBSManager _Instance = new TopBBSManager();
/**
* @return
*/
public static TopBBSManager getInstance()
{
return _Instance;
}
}

View File

@@ -0,0 +1,472 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.communitybbs.Manager;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import com.l2jmobius.gameserver.communitybbs.BB.Forum;
import com.l2jmobius.gameserver.communitybbs.BB.Post;
import com.l2jmobius.gameserver.communitybbs.BB.Topic;
import com.l2jmobius.gameserver.datatables.ClanTable;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ShowBoard;
import javolution.text.TextBuilder;
import javolution.util.FastList;
import javolution.util.FastMap;
public class TopicBBSManager extends BaseBBSManager
{
private final List<Topic> _table;
private final Map<Forum, Integer> _Maxid;
private static TopicBBSManager _Instance;
public static TopicBBSManager getInstance()
{
if (_Instance == null)
{
_Instance = new TopicBBSManager();
}
return _Instance;
}
public TopicBBSManager()
{
_table = new FastList<>();
_Maxid = new FastMap<Forum, Integer>().shared();
}
public void addTopic(Topic tt)
{
_table.add(tt);
}
/**
* @param topic
*/
public void delTopic(Topic topic)
{
_table.remove(topic);
}
public void setMaxID(int id, Forum f)
{
_Maxid.put(f, id);
}
public int getMaxID(Forum f)
{
final Integer i = _Maxid.get(f);
if (i == null)
{
return 0;
}
return i;
}
public Topic getTopicByID(int idf)
{
for (final Topic t : _table)
{
if (t.getID() == idf)
{
return t;
}
}
return null;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsewrite(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsewrite(String ar1, String ar2, String ar3, String ar4, String ar5, L2PcInstance activeChar)
{
if (ar1.equals("crea"))
{
final Forum f = ForumsBBSManager.getInstance().getForumByID(Integer.parseInt(ar2));
if (f == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + ar2 + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
f.vload();
final Topic t = new Topic(Topic.ConstructorType.CREATE, TopicBBSManager.getInstance().getMaxID(f) + 1, Integer.parseInt(ar2), ar5, Calendar.getInstance().getTimeInMillis(), activeChar.getName(), activeChar.getObjectId(), Topic.MEMO, 0);
f.addtopic(t);
TopicBBSManager.getInstance().setMaxID(t.getID(), f);
final Post p = new Post(activeChar.getName(), activeChar.getObjectId(), Calendar.getInstance().getTimeInMillis(), t.getID(), f.getID(), ar4);
PostBBSManager.getInstance().addPostByTopic(p, t);
parsecmd("_bbsmemo", activeChar);
}
}
else if (ar1.equals("del"))
{
final Forum f = ForumsBBSManager.getInstance().getForumByID(Integer.parseInt(ar2));
if (f == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + ar2 + " does not exist !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
final Topic t = f.gettopic(Integer.parseInt(ar3));
if (t == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + ar3 + " does not exist !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
// CPost cp = null;
final Post p = PostBBSManager.getInstance().getGPosttByTopic(t);
if (p != null)
{
p.deleteme(t);
}
t.deleteme(f);
parsecmd("_bbsmemo", activeChar);
}
}
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + ar1 + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public void parsecmd(String command, L2PcInstance activeChar)
{
if (command.equals("_bbsmemo"))
{
showTopics(activeChar.getMemo(), activeChar, 1, activeChar.getMemo().getID());
}
else if (command.startsWith("_bbstopics;read"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
st.nextToken();
final int idf = Integer.parseInt(st.nextToken());
String index = null;
if (st.hasMoreTokens())
{
index = st.nextToken();
}
int ind = 0;
if (index == null)
{
ind = 1;
}
else
{
ind = Integer.parseInt(index);
}
showTopics(ForumsBBSManager.getInstance().getForumByID(idf), activeChar, ind, idf);
}
else if (command.startsWith("_bbstopics;crea"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
st.nextToken();
final int idf = Integer.parseInt(st.nextToken());
showNewTopic(ForumsBBSManager.getInstance().getForumByID(idf), activeChar, idf);
}
else if (command.startsWith("_bbstopics;del"))
{
final StringTokenizer st = new StringTokenizer(command, ";");
st.nextToken();
st.nextToken();
final int idf = Integer.parseInt(st.nextToken());
final int idt = Integer.parseInt(st.nextToken());
final Forum f = ForumsBBSManager.getInstance().getForumByID(idf);
if (f == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " does not exist !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
final Topic t = f.gettopic(idt);
if (t == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + idt + " does not exist !</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else
{
// CPost cp = null;
final Post p = PostBBSManager.getInstance().getGPosttByTopic(t);
if (p != null)
{
p.deleteme(t);
}
t.deleteme(f);
parsecmd("_bbsmemo", activeChar);
}
}
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/**
* @param forum
* @param activeChar
* @param idf
*/
private void showNewTopic(Forum forum, L2PcInstance activeChar, int idf)
{
if (forum == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else if (forum.getType() == Forum.MEMO)
{
ShowMemoNewTopics(forum, activeChar);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName() + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/**
* @param forum
* @param activeChar
*/
private void ShowMemoNewTopics(Forum forum, L2PcInstance activeChar)
{
final TextBuilder html = new TextBuilder("<html>");
html.append("<body><br><br>");
html.append("<table border=0 width=610><tr><td width=10></td><td width=600 align=left>");
html.append("<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>");
html.append("</td></tr>");
html.append("</table>");
html.append("<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");
html.append("<center>");
html.append("<table border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td width=610><img src=\"sek.cbui355\" width=\"610\" height=\"1\"><br1><img src=\"sek.cbui355\" width=\"610\" height=\"1\"></td></tr>");
html.append("</table>");
html.append("<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=20></td></tr>");
html.append("<tr>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("<td align=center FIXWIDTH=60 height=29>&$413;</td>");
html.append("<td FIXWIDTH=540><edit var = \"Title\" width=540 height=13></td>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("</tr></table>");
html.append("<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>");
html.append("<tr>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("<td align=center FIXWIDTH=60 height=29 valign=top>&$427;</td>");
html.append("<td align=center FIXWIDTH=540><MultiEdit var =\"Content\" width=535 height=313></td>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("</tr>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>");
html.append("</table>");
html.append("<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>");
html.append("<tr>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("<td align=center FIXWIDTH=60 height=29>&nbsp;</td>");
html.append("<td align=center FIXWIDTH=70><button value=\"&$140;\" action=\"Write Topic crea " + forum.getID() + " Title Content Title\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>");
html.append("<td align=center FIXWIDTH=70><button value = \"&$141;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td>");
html.append("<td align=center FIXWIDTH=400>&nbsp;</td>");
html.append("<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>");
html.append("</tr></table>");
html.append("</center>");
html.append("</body>");
html.append("</html>");
send1001(html.toString(), activeChar);
send1002(activeChar);
}
/**
* @param forum
* @param activeChar
* @param index
* @param idf
*/
private void showTopics(Forum forum, L2PcInstance activeChar, int index, int idf)
{
if (forum == null)
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
else if (forum.getType() == Forum.MEMO)
{
ShowMemoTopics(forum, activeChar, index);
}
else
{
final ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName() + " is not implemented yet</center><br><br></body></html>", "101");
activeChar.sendPacket(sb);
activeChar.sendPacket(new ShowBoard(null, "102"));
activeChar.sendPacket(new ShowBoard(null, "103"));
}
}
/**
* @param forum
* @param activeChar
* @param index
*/
private void ShowMemoTopics(Forum forum, L2PcInstance activeChar, int index)
{
forum.vload();
final TextBuilder html = new TextBuilder("<html><body><br><br>");
html.append("<table border=0 width=610><tr><td width=10></td><td width=600 align=left>");
html.append("<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>");
html.append("</td></tr>");
html.append("</table>");
html.append("<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">");
html.append("<center>");
html.append("<table border=0 cellspacing=0 cellpadding=2 bgcolor=888888 width=610>");
html.append("<tr>");
html.append("<td FIXWIDTH=5></td>");
html.append("<td FIXWIDTH=415 align=center>&$413;</td>");
html.append("<td FIXWIDTH=120 align=center></td>");
html.append("<td FIXWIDTH=70 align=center>&$418;</td>");
html.append("</tr>");
html.append("</table>");
for (int i = 0, j = getMaxID(forum) + 1; i < (12 * index); j--)
{
if (j < 0)
{
break;
}
final Topic t = forum.gettopic(j);
if (t != null)
{
if (i++ >= (12 * (index - 1)))
{
html.append("<table border=0 cellspacing=0 cellpadding=5 WIDTH=610>");
html.append("<tr>");
html.append("<td FIXWIDTH=5></td>");
html.append("<td FIXWIDTH=415><a action=\"bypass _bbsposts;read;" + forum.getID() + ";" + t.getID() + "\">" + t.getName() + "</a></td>");
html.append("<td FIXWIDTH=120 align=center></td>");
html.append("<td FIXWIDTH=70 align=center>" + DateFormat.getInstance().format(new Date(t.getDate())) + "</td>");
html.append("</tr>");
html.append("</table>");
html.append("<img src=\"L2UI.Squaregray\" width=\"610\" height=\"1\">");
}
}
}
html.append("<br>");
html.append("<table width=610 cellspace=0 cellpadding=0>");
html.append("<tr>");
html.append("<td width=50>");
html.append("<button value=\"&$422;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\">");
html.append("</td>");
html.append("<td width=510 align=center>");
html.append("<table border=0><tr>");
if (index == 1)
{
html.append("<td><button action=\"\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
}
else
{
html.append("<td><button action=\"bypass _bbstopics;read;" + forum.getID() + ";" + (index - 1) + "\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
}
int nbp;
nbp = forum.getTopicSize() / 8;
if ((nbp * 8) != ClanTable.getInstance().getClans().length)
{
nbp++;
}
for (int i = 1; i <= nbp; i++)
{
if (i == index)
{
html.append("<td> " + i + " </td>");
}
else
{
html.append("<td><a action=\"bypass _bbstopics;read;" + forum.getID() + ";" + i + "\"> " + i + " </a></td>");
}
}
if (index == nbp)
{
html.append("<td><button action=\"\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
}
else
{
html.append("<td><button action=\"bypass _bbstopics;read;" + forum.getID() + ";" + (index + 1) + "\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
}
html.append("</tr></table> </td> ");
html.append("<td align=right><button value = \"&$421;\" action=\"bypass _bbstopics;crea;" + forum.getID() + "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td></tr>");
html.append("<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>");
html.append("<tr> ");
html.append("<td></td>");
html.append("<td align=center><table border=0><tr><td></td><td><edit var = \"Search\" width=130 height=11></td>");
html.append("<td><button value=\"&$420;\" action=\"Write 5 -2 0 Search _ _\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td> </tr></table> </td>");
html.append("</tr>");
html.append("</table>");
html.append("<br>");
html.append("<br>");
html.append("<br>");
html.append("</center>");
html.append("</body>");
html.append("</html>");
separateAndSend(html.toString(), activeChar);
}
}

View File

@@ -0,0 +1,120 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2ArmorSet;
import javolution.util.FastMap;
/**
* @author Luno
*/
public class ArmorSetsTable
{
private static Logger _log = Logger.getLogger(ArmorSetsTable.class.getName());
private static ArmorSetsTable _instance;
private final FastMap<Integer, L2ArmorSet> _armorSets;
public static ArmorSetsTable getInstance()
{
if (_instance == null)
{
_instance = new ArmorSetsTable();
}
return _instance;
}
private ArmorSetsTable()
{
_armorSets = new FastMap<>();
loadData();
}
private void loadData()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT chest, legs, head, gloves, feet, skill_id, shield, shield_skill_id FROM armorsets");
ResultSet rset = statement.executeQuery())
{
while (rset.next())
{
final int chest = rset.getInt("chest");
final int legs = rset.getInt("legs");
final int head = rset.getInt("head");
final int gloves = rset.getInt("gloves");
final int feet = rset.getInt("feet");
final int skill_id = rset.getInt("skill_id");
final int shield = rset.getInt("shield");
final int shield_skill_id = rset.getInt("shield_skill_id");
_armorSets.put(chest, new L2ArmorSet(chest, legs, head, gloves, feet, skill_id, shield, shield_skill_id));
}
_log.config("ArmorSetsTable: Loaded " + _armorSets.size() + " armor sets.");
}
catch (final Exception e)
{
_log.severe("ArmorSetsTable: Error reading ArmorSets table: " + e);
}
if (Config.CUSTOM_ARMORSETS_TABLE)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT chest, legs, head, gloves, feet, skill_id, shield, shield_skill_id FROM custom_armorsets");
ResultSet rset = statement.executeQuery())
{
final int cSets = _armorSets.size();
while (rset.next())
{
final int chest = rset.getInt("chest");
final int legs = rset.getInt("legs");
final int head = rset.getInt("head");
final int gloves = rset.getInt("gloves");
final int feet = rset.getInt("feet");
final int skill_id = rset.getInt("skill_id");
final int shield = rset.getInt("shield");
final int shield_skill_id = rset.getInt("shield_skill_id");
_armorSets.put(chest, new L2ArmorSet(chest, legs, head, gloves, feet, skill_id, shield, shield_skill_id));
}
_log.config("ArmorSetsTable: Loaded " + (_armorSets.size() - cSets) + " custom armor sets.");
}
catch (final Exception e)
{
_log.severe("ArmorSetsTable: Error reading Custom ArmorSets table: " + e);
}
}
}
public boolean setExists(int chestId)
{
return _armorSets.containsKey(chestId);
}
public L2ArmorSet getSet(int chestId)
{
return _armorSets.get(chestId);
}
}

View File

@@ -0,0 +1,88 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
/**
* This class ...
* @version $Revision: 1.3.2.2.2.1 $ $Date: 2005/03/27 15:29:18 $
*/
public class CharNameTable
{
private static Logger _log = Logger.getLogger(CharNameTable.class.getName());
private static CharNameTable _instance;
public static CharNameTable getInstance()
{
if (_instance == null)
{
_instance = new CharNameTable();
}
return _instance;
}
public boolean doesCharNameExist(String name)
{
boolean result = true;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT account_name FROM characters WHERE char_name=?"))
{
statement.setString(1, name);
try (ResultSet rset = statement.executeQuery())
{
result = rset.next();
}
}
catch (final SQLException e)
{
_log.warning("could not check existing charname:" + e.getMessage());
}
return result;
}
public int accountCharNumber(String account)
{
int number = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT COUNT(char_name) FROM characters WHERE account_name=?"))
{
statement.setString(1, account);
try (ResultSet rset = statement.executeQuery())
{
while (rset.next())
{
number = rset.getInt(1);
}
}
}
catch (final SQLException e)
{
_log.warning("could not check existing char number:" + e.getMessage());
}
return number;
}
}

View File

@@ -0,0 +1,300 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.templates.L2PcTemplate;
import com.l2jmobius.gameserver.templates.StatsSet;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.6.2.1.2.10 $ $Date: 2005/03/29 14:00:54 $
*/
public class CharTemplateTable
{
private static Logger _log = Logger.getLogger(CharTemplateTable.class.getName());
private static CharTemplateTable _instance;
public static final String[] charClasses =
{
"Human Fighter",
"Warrior",
"Gladiator",
"Warlord",
"Human Knight",
"Paladin",
"Dark Avenger",
"Rogue",
"Treasure Hunter",
"Hawkeye",
"Human Mystic",
"Human Wizard",
"Sorcerer",
"Necromancer",
"Warlock",
"Cleric",
"Bishop",
"Prophet",
"Elven Fighter",
"Elven Knight",
"Temple Knight",
"Swordsinger",
"Elven Scout",
"Plainswalker",
"Silver Ranger",
"Elven Mystic",
"Elven Wizard",
"Spellsinger",
"Elemental Summoner",
"Elven Oracle",
"Elven Elder",
"Dark Fighter",
"Palus Knight",
"Shillien Knight",
"Bladedancer",
"Assassin",
"Abyss Walker",
"Phantom Ranger",
"Dark Elven Mystic",
"Dark Elven Wizard",
"Spellhowler",
"Phantom Summoner",
"Shillien Oracle",
"Shillien Elder",
"Orc Fighter",
"Orc Raider",
"Destroyer",
"Orc Monk",
"Tyrant",
"Orc Mystic",
"Orc Shaman",
"Overlord",
"Warcryer",
"Dwarven Fighter",
"Dwarven Scavenger",
"Bounty Hunter",
"Dwarven Artisan",
"Warsmith",
"dummyEntry1",
"dummyEntry2",
"dummyEntry3",
"dummyEntry4",
"dummyEntry5",
"dummyEntry6",
"dummyEntry7",
"dummyEntry8",
"dummyEntry9",
"dummyEntry10",
"dummyEntry11",
"dummyEntry12",
"dummyEntry13",
"dummyEntry14",
"dummyEntry15",
"dummyEntry16",
"dummyEntry17",
"dummyEntry18",
"dummyEntry19",
"dummyEntry20",
"dummyEntry21",
"dummyEntry22",
"dummyEntry23",
"dummyEntry24",
"dummyEntry25",
"dummyEntry26",
"dummyEntry27",
"dummyEntry28",
"dummyEntry29",
"dummyEntry30",
"Duelist",
"Dreadnought",
"Phoenix Knight",
"Hell Knight",
"Sagittarius",
"Adventurer",
"Archmage",
"Soultaker",
"Arcana Lord",
"Cardinal",
"Hierophant",
"Eva Templar",
"Sword Muse",
"Wind Rider",
"Moonlight Sentinel",
"Mystic Muse",
"Elemental Master",
"Eva's Saint",
"Shillien Templar",
"Spectral Dancer",
"Ghost Hunter",
"Ghost Sentinel",
"Storm Screamer",
"Spectral Master",
"Shillien Saint",
"Titan",
"Grand Khavatari",
"Dominator",
"Doomcryer",
"Fortune Seeker",
"Maestro"
};
private final Map<Integer, L2PcTemplate> _templates;
public static CharTemplateTable getInstance()
{
if (_instance == null)
{
_instance = new CharTemplateTable();
}
return _instance;
}
private CharTemplateTable()
{
_templates = new FastMap<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM class_list, char_templates, lvlupgain" + " WHERE class_list.id = char_templates.classId" + " AND class_list.id = lvlupgain.classId" + " ORDER BY class_list.id");
ResultSet rset = statement.executeQuery())
{
while (rset.next())
{
final StatsSet set = new StatsSet();
set.set("classId", rset.getInt("id"));
set.set("className", rset.getString("className"));
set.set("raceId", rset.getInt("raceId"));
set.set("baseSTR", rset.getInt("STR"));
set.set("baseCON", rset.getInt("CON"));
set.set("baseDEX", rset.getInt("DEX"));
set.set("baseINT", rset.getInt("_INT"));
set.set("baseWIT", rset.getInt("WIT"));
set.set("baseMEN", rset.getInt("MEN"));
set.set("baseHpMax", rset.getFloat("defaultHpBase"));
set.set("lvlHpAdd", rset.getFloat("defaultHpAdd"));
set.set("lvlHpMod", rset.getFloat("defaultHpMod"));
set.set("baseMpMax", rset.getFloat("defaultMpBase"));
set.set("baseCpMax", rset.getFloat("defaultCpBase"));
set.set("lvlCpAdd", rset.getFloat("defaultCpAdd"));
set.set("lvlCpMod", rset.getFloat("defaultCpMod"));
set.set("lvlMpAdd", rset.getFloat("defaultMpAdd"));
set.set("lvlMpMod", rset.getFloat("defaultMpMod"));
set.set("baseHpReg", 1.5);
set.set("baseMpReg", 0.9);
set.set("basePAtk", rset.getInt("p_atk"));
set.set("basePDef", rset.getInt("p_def"));
set.set("baseMAtk", rset.getInt("m_atk"));
set.set("baseMDef", rset.getInt("char_templates.m_def"));
set.set("classBaseLevel", rset.getInt("class_lvl"));
set.set("basePAtkSpd", rset.getInt("p_spd"));
set.set("baseMAtkSpd", rset.getInt("char_templates.m_spd"));
set.set("baseCritRate", rset.getInt("char_templates.critical") / 10);
set.set("baseRunSpd", rset.getInt("move_spd"));
set.set("baseWalkSpd", 0);
set.set("baseShldDef", 0);
set.set("baseShldRate", 0);
set.set("baseAtkRange", 40);
set.set("spawnX", rset.getInt("x"));
set.set("spawnY", rset.getInt("y"));
set.set("spawnZ", rset.getInt("z"));
L2PcTemplate ct;
set.set("collision_radius", rset.getDouble("m_col_r"));
set.set("collision_height", rset.getDouble("m_col_h"));
set.set("collision_radius_female", rset.getDouble("f_col_r"));
set.set("collision_height_female", rset.getDouble("f_col_h"));
ct = new L2PcTemplate(set);
// 5 items must go here
for (int x = 1; x < 6; x++)
{
if (rset.getInt("items" + x) != 0)
{
ct.addItem(rset.getInt("items" + x));
}
}
_templates.put(ct.classId.getId(), ct);
}
}
catch (final SQLException e)
{
_log.warning("error while loading char templates " + e.getMessage());
}
_log.config("CharTemplateTable: Loaded " + _templates.size() + " Character Templates.");
}
public L2PcTemplate getTemplate(ClassId classId)
{
return getTemplate(classId.getId());
}
public L2PcTemplate getTemplate(int classId)
{
return _templates.get(classId);
}
public static final String getClassNameById(int classId)
{
return charClasses[classId];
}
public static final int getClassIdByName(String className)
{
int currId = 1;
for (final String name : charClasses)
{
if (name.equalsIgnoreCase(className))
{
break;
}
currId++;
}
return currId;
}
}

View File

@@ -0,0 +1,421 @@
/*
* 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 2, 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* http://www.gnu.org/copyleft/gpl.html
*/
package com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.AuctionManager;
import com.l2jmobius.gameserver.instancemanager.ClanHallManager;
import com.l2jmobius.gameserver.instancemanager.SiegeManager;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Siege;
import com.l2jmobius.gameserver.network.serverpackets.PledgeShowInfoUpdate;
import com.l2jmobius.gameserver.network.serverpackets.PledgeShowMemberListAll;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.network.serverpackets.UserInfo;
import com.l2jmobius.gameserver.util.Util;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.11.2.5.2.5 $ $Date: 2005/03/27 15:29:18 $
*/
public class ClanTable
{
private static Logger _log = Logger.getLogger(ClanTable.class.getName());
private static ClanTable _instance;
private final Map<Integer, L2Clan> _clans;
public static ClanTable getInstance()
{
if (_instance == null)
{
_instance = new ClanTable();
}
return _instance;
}
public L2Clan[] getClans()
{
return _clans.values().toArray(new L2Clan[_clans.size()]);
}
private ClanTable()
{
_clans = new FastMap<>();
L2Clan clan;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM clan_data");
ResultSet result = statement.executeQuery())
{
// Count the clans
int clanCount = 0;
while (result.next())
{
_clans.put(Integer.parseInt(result.getString("clan_id")), new L2Clan(Integer.parseInt(result.getString("clan_id"))));
clan = getClan(Integer.parseInt(result.getString("clan_id")));
if (clan.getDissolvingExpiryTime() != 0)
{
if (clan.getDissolvingExpiryTime() < System.currentTimeMillis())
{
destroyClan(clan.getClanId());
}
else
{
scheduleRemoveClan(clan.getClanId());
}
}
clanCount++;
}
_log.config("Restored " + clanCount + " clans from the database.");
}
catch (final Exception e)
{
_log.warning("data error on ClanTable: " + e);
e.printStackTrace();
}
}
/**
* @param clanId
* @return
*/
public L2Clan getClan(int clanId)
{
final L2Clan clan = _clans.get(new Integer(clanId));
return clan;
}
public L2Clan getClanByName(String clanName)
{
for (final L2Clan clan : getClans())
{
if (clan.getName().equalsIgnoreCase(clanName))
{
return clan;
}
}
return null;
}
public L2Clan createClan(L2PcInstance player, String clanName)
{
if (player == null)
{
return null;
}
if (Config.DEBUG)
{
_log.fine(player.getObjectId() + "(" + player.getName() + ") requested a clan creation.");
}
if (player.getLevel() < 10)
{
player.sendPacket(new SystemMessage(SystemMessage.FAILED_TO_CREATE_CLAN));
return null;
}
if (player.getClanId() != 0)
{
player.sendPacket(new SystemMessage(SystemMessage.FAILED_TO_CREATE_CLAN));
return null;
}
if (player.getClanCreateExpiryTime() > System.currentTimeMillis())
{
player.sendPacket(new SystemMessage(SystemMessage.YOU_MUST_WAIT_XX_DAYS_BEFORE_CREATING_A_NEW_CLAN));
return null;
}
if (!Util.isAlphaNumeric(clanName) || (clanName.length() < 2))
{
player.sendPacket(new SystemMessage(SystemMessage.CLAN_NAME_INCORRECT));
return null;
}
if (clanName.length() > 16)
{
player.sendPacket(new SystemMessage(SystemMessage.CLAN_NAME_TOO_LONG));
return null;
}
if (getClanByName(clanName) != null)
{
player.sendMessage("Clan name already exists.");
return null;
}
final L2ClanMember leader = new L2ClanMember(player.getName(), player.getLevel(), player.getClassId().getId(), player.getObjectId());
final L2Clan clan = new L2Clan(IdFactory.getInstance().getNextId(), clanName, leader);
leader.setPlayerInstance(player);
clan.store();
player.setClan(clan);
player.setClanPrivileges(L2Clan.CP_ALL);
if (Config.DEBUG)
{
_log.fine("New clan created: " + clan.getClanId() + " " + clan.getName());
}
_clans.put(new Integer(clan.getClanId()), clan);
// should be update packet only
player.sendPacket(new PledgeShowInfoUpdate(clan));
player.sendPacket(new PledgeShowMemberListAll(clan, player));
player.sendPacket(new UserInfo(player));
player.sendPacket(new SystemMessage(SystemMessage.CLAN_CREATED));
return clan;
}
public void destroyClan(int clanId)
{
final L2Clan clan = getClan(clanId);
if (clan == null)
{
return;
}
clan.broadcastToOnlineMembers(new SystemMessage(193));
if (AuctionManager.getInstance().getAuction(clan.getAuctionBiddedAt()) != null)
{
AuctionManager.getInstance().getAuction(clan.getAuctionBiddedAt()).cancelBid(clan.getClanId());
}
if (clan.getHasHideout() != 0)
{
ClanHallManager.getInstance().getClanHallByOwner(clan).setOwner(null);
}
final int castleId = clan.getHasCastle();
if (castleId == 0)
{
for (final Siege siege : SiegeManager.getInstance().getSieges())
{
siege.removeSiegeClan(clanId);
}
}
final L2ClanMember leaderMember = clan.getLeader();
if (leaderMember == null)
{
clan.getWarehouse().destroyAllItems("ClanRemove", null, null);
}
else
{
clan.getWarehouse().destroyAllItems("ClanRemove", clan.getLeader().getPlayerInstance(), null);
}
for (final L2ClanMember member : clan.getMembers())
{
clan.removeClanMember(member.getObjectId(), 0);
}
_clans.remove(clanId);
IdFactory.getInstance().releaseId(clanId);
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
try (PreparedStatement statement = con.prepareStatement("UPDATE characters SET clanid = 0, clan_privs = 0 WHERE clanid=?"))
{
statement.setInt(1, clanId);
statement.execute();
}
try (PreparedStatement statement = con.prepareStatement("DELETE FROM clan_data WHERE clan_id=?"))
{
statement.setInt(1, clanId);
statement.execute();
}
try (PreparedStatement statement = con.prepareStatement("DELETE FROM clan_wars WHERE clan1=? OR clan2=?"))
{
statement.setInt(1, clanId);
statement.setInt(2, clanId);
statement.execute();
}
if (castleId != 0)
{
try (PreparedStatement statement = con.prepareStatement("UPDATE castle SET taxPercent = 0 WHERE id = ?"))
{
statement.setInt(1, castleId);
statement.execute();
}
}
}
catch (final Exception e)
{
_log.warning("could not dissolve clan:" + e);
}
}
public boolean isAllyExists(String allyName)
{
for (final L2Clan clan : getClans())
{
if ((clan.getAllyName() != null) && clan.getAllyName().equalsIgnoreCase(allyName))
{
return true;
}
}
return false;
}
public void storeclanswars(int clanId1, int clanId2)
{
final L2Clan clan1 = ClanTable.getInstance().getClan(clanId1);
final L2Clan clan2 = ClanTable.getInstance().getClan(clanId2);
clan1.setEnemyClan(clan2);
clan1.broadcastClanStatus();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("REPLACE INTO clan_wars (clan1, clan2, wantspeace1, wantspeace2) VALUES(?,?,?,?)"))
{
statement.setInt(1, clanId1);
statement.setInt(2, clanId2);
statement.setInt(3, 0);
statement.setInt(4, 0);
statement.execute();
}
catch (final Exception e)
{
_log.warning("could not store clans wars data:" + e);
}
SystemMessage msg = new SystemMessage(1562);
msg.addString(clan2.getName());
clan1.broadcastToOnlineMembers(msg);
// clan1 declared clan war.
msg = new SystemMessage(1561);
msg.addString(clan1.getName());
clan2.broadcastToOnlineMembers(msg);
}
public void deleteclanswars(int clanId1, int clanId2)
{
final L2Clan clan1 = ClanTable.getInstance().getClan(clanId1);
final L2Clan clan2 = ClanTable.getInstance().getClan(clanId2);
clan1.deleteEnemyClan(clan2);
clan1.broadcastClanStatus();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM clan_wars WHERE clan1=? AND clan2=?"))
{
statement.setInt(1, clanId1);
statement.setInt(2, clanId2);
statement.execute();
}
catch (final Exception e)
{
_log.warning("could not restore clans wars data:" + e);
}
SystemMessage msg = new SystemMessage(1567);
msg.addString(clan2.getName());
clan1.broadcastToOnlineMembers(msg);
msg = new SystemMessage(1566);
msg.addString(clan1.getName());
clan2.broadcastToOnlineMembers(msg);
}
public void CheckSurrender(L2Clan clan1, L2Clan clan2)
{
int count = 0;
for (final L2ClanMember player : clan1.getMembers())
{
if ((player != null) && (player.getPlayerInstance().getWantsPeace() == 1))
{
count++;
}
}
if (count == (clan1.getMembers().length - 1))
{
clan1.deleteEnemyClan(clan2);
clan2.deleteEnemyClan(clan1);
deleteclanswars(clan1.getClanId(), clan2.getClanId());
}
}
public void scheduleRemoveClan(final int clanId)
{
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (getClan(clanId) == null)
{
return;
}
if (getClan(clanId).getDissolvingExpiryTime() != 0)
{
destroyClan(clanId);
}
}, getClan(clanId).getDissolvingExpiryTime() - System.currentTimeMillis());
}
}

View File

@@ -0,0 +1,378 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.ClanHallManager;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.entity.ClanHall;
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
import com.l2jmobius.gameserver.templates.L2CharTemplate;
import com.l2jmobius.gameserver.templates.StatsSet;
import javolution.util.FastMap;
public class DoorTable
{
private static Logger _log = Logger.getLogger(DoorTable.class.getName());
private Map<Integer, L2DoorInstance> _staticItems;
private static DoorTable _instance;
public static DoorTable getInstance()
{
if (_instance == null)
{
_instance = new DoorTable();
}
return _instance;
}
public DoorTable()
{
_staticItems = new FastMap<>();
}
public void reloadAll()
{
respawn();
}
public void respawn()
{
_staticItems = null;
_instance = null;
_instance = new DoorTable();
}
public void parseData()
{
final File doorData = new File(Config.DATAPACK_ROOT, "data/door.csv");
try (FileReader fr = new FileReader(doorData);
BufferedReader br = new BufferedReader(fr);
LineNumberReader lnr = new LineNumberReader(br))
{
String line = null;
_log.warning("Searching clan halls doors:");
while ((line = lnr.readLine()) != null)
{
if ((line.trim().length() == 0) || line.startsWith("#"))
{
continue;
}
final L2DoorInstance door = parseList(line);
putDoor(door);
door.spawnMe(door.getX(), door.getY(), door.getZ());
final ClanHall clanhall = ClanHallManager.getInstance().getNearbyClanHall(door.getX(), door.getY(), 500);
if (clanhall != null)
{
clanhall.getDoors().add(door);
door.setClanHall(clanhall);
if (Config.DEBUG)
{
_log.warning("door " + door.getDoorName() + " attached to ch " + clanhall.getName());
}
}
}
_log.config("DoorTable: Loaded " + _staticItems.size() + " Door Templates.");
}
catch (final FileNotFoundException e)
{
_initialized = false;
_log.warning("door.csv is missing in data folder");
}
catch (final IOException e)
{
_initialized = false;
_log.warning("error while creating door table " + e);
}
}
public static L2DoorInstance parseList(String line)
{
final StringTokenizer st = new StringTokenizer(line, ";");
final String name = st.nextToken();
final int id = Integer.parseInt(st.nextToken());
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int rangeXMin = Integer.parseInt(st.nextToken());
final int rangeYMin = Integer.parseInt(st.nextToken());
final int rangeZMin = Integer.parseInt(st.nextToken());
final int rangeXMax = Integer.parseInt(st.nextToken());
final int rangeYMax = Integer.parseInt(st.nextToken());
final int rangeZMax = Integer.parseInt(st.nextToken());
final int hp = Integer.parseInt(st.nextToken());
final int pdef = Integer.parseInt(st.nextToken());
final int mdef = Integer.parseInt(st.nextToken());
boolean unlockable = false;
if (st.hasMoreTokens())
{
unlockable = Boolean.parseBoolean(st.nextToken());
}
if (rangeXMin > rangeXMax)
{
_log.severe("Error in door data, XMin > XMax, ID:" + id);
}
if (rangeYMin > rangeYMax)
{
_log.severe("Error in door data, YMin > YMax, ID:" + id);
}
if (rangeZMin > rangeZMax)
{
_log.severe("Error in door data, ZMin > ZMax, ID:" + id);
}
int collisionRadius; // (max) radius for movement checks
if ((rangeXMax - rangeXMin) > (rangeYMax - rangeYMin))
{
collisionRadius = rangeYMax - rangeYMin;
}
else
{
collisionRadius = rangeXMax - rangeXMin;
}
final StatsSet npcDat = new StatsSet();
npcDat.set("npcId", id);
npcDat.set("level", 0);
npcDat.set("jClass", "door");
npcDat.set("baseSTR", 0);
npcDat.set("baseCON", 0);
npcDat.set("baseDEX", 0);
npcDat.set("baseINT", 0);
npcDat.set("baseWIT", 0);
npcDat.set("baseMEN", 0);
npcDat.set("baseShldDef", 0);
npcDat.set("baseShldRate", 0);
npcDat.set("baseAccCombat", 38);
npcDat.set("baseEvasRate", 38);
npcDat.set("baseCritRate", 38);
npcDat.set("collision_radius", collisionRadius);
npcDat.set("collision_height", rangeZMax - rangeZMin);
npcDat.set("sex", "male");
npcDat.set("type", "");
npcDat.set("baseAtkRange", 0);
npcDat.set("baseMpMax", 0);
npcDat.set("baseCpMax", 0);
npcDat.set("rewardExp", 0);
npcDat.set("rewardSp", 0);
npcDat.set("basePAtk", 0);
npcDat.set("baseMAtk", 0);
npcDat.set("basePAtkSpd", 0);
npcDat.set("aggroRange", 0);
npcDat.set("baseMAtkSpd", 0);
npcDat.set("rhand", 0);
npcDat.set("lhand", 0);
npcDat.set("armor", 0);
npcDat.set("baseWalkSpd", 0);
npcDat.set("baseRunSpd", 0);
npcDat.set("name", name);
npcDat.set("baseHpMax", hp);
npcDat.set("baseHpReg", 3.e-3f);
npcDat.set("baseMpReg", 3.e-3f);
npcDat.set("basePDef", pdef);
npcDat.set("baseMDef", mdef);
final L2CharTemplate template = new L2CharTemplate(npcDat);
final L2DoorInstance door = new L2DoorInstance(IdFactory.getInstance().getNextId(), template, id, name, unlockable);
door.setRange(rangeXMin, rangeYMin, rangeZMin, rangeXMax, rangeYMax, rangeZMax);
try
{
door.setMapRegion(MapRegionTable.getInstance().getMapRegion(x, y));
}
catch (final Exception e)
{
_log.severe("Error in door data, ID:" + id);
}
door.setCurrentHpMp(door.getMaxHp(), door.getMaxMp());
door.setOpen(1);
door.setXYZInvisible(x, y, z);
door.setMapRegion(MapRegionTable.getInstance().getMapRegion(x, y));
return door;
}
private boolean _initialized = true;
public boolean isInitialized()
{
return _initialized;
}
public L2DoorInstance getDoor(Integer id)
{
return _staticItems.get(id);
}
public void putDoor(L2DoorInstance door)
{
_staticItems.put(door.getDoorId(), door);
}
public L2DoorInstance[] getDoors()
{
final L2DoorInstance[] _allTemplates = _staticItems.values().toArray(new L2DoorInstance[_staticItems.size()]);
return _allTemplates;
}
/**
* Performs a check and sets up a scheduled task for those doors that require auto opening/closing.
*/
public void checkAutoOpen()
{
for (final L2DoorInstance doorInst : getDoors())
{
if (doorInst.isUnlockable())
{
continue;
}
// Garden of Eva (every 7 minutes)
if (doorInst.getDoorName().startsWith("goe"))
{
doorInst.setAutoActionDelay(420000);
}
else if (doorInst.getDoorName().startsWith("aden_tower"))
{
doorInst.setAutoActionDelay(300000);
}
else if (doorInst.getDoorName().startsWith("pirate_isle"))
{
doorInst.setAutoActionDelay(300000);
}
else if (doorInst.getDoorName().startsWith("cruma"))
{
doorInst.setAutoActionDelay(1200000);
}
}
}
public boolean checkIfDoorsBetween(AbstractNodeLoc start, AbstractNodeLoc end)
{
return checkIfDoorsBetween(start.getX(), start.getY(), start.getZ(), end.getX(), end.getY(), end.getZ());
}
public boolean checkIfDoorsBetween(int x, int y, int z, int tx, int ty, int tz)
{
int region;
try
{
region = MapRegionTable.getInstance().getMapRegion(x, y);
}
catch (final Exception e)
{
return false;
}
// there are quite many doors, maybe they should be splitted
for (final L2DoorInstance doorInst : getDoors())
{
if (doorInst.getMapRegion() != region)
{
continue;
}
if (doorInst.getXMax() == 0)
{
continue;
}
// line segment goes through box
// first basic checks to stop most calculations short
// phase 1, x
if (((x <= doorInst.getXMax()) && (tx >= doorInst.getXMin())) || ((tx <= doorInst.getXMax()) && (x >= doorInst.getXMin())))
{
// phase 2, y
if (((y <= doorInst.getYMax()) && (ty >= doorInst.getYMin())) || ((ty <= doorInst.getYMax()) && (y >= doorInst.getYMin())))
{
// phase 3, basically only z remains but now we calculate it with another formula (by rage)
// in some cases the direct line check (only) in the beginning isn't sufficient,
// when char z changes a lot along the path
if ((doorInst.getCurrentHp() > 0) && (doorInst.getOpen() != 0))
{
final int px1 = doorInst.getXMin();
final int py1 = doorInst.getYMin();
final int pz1 = doorInst.getZMin();
final int px2 = doorInst.getXMax();
final int py2 = doorInst.getYMax();
final int pz2 = doorInst.getZMax();
final int l = tx - x;
final int m = ty - y;
final int n = tz - z;
int dk;
if ((dk = ((doorInst.getA() * l) + (doorInst.getB() * m) + (doorInst.getC() * n))) == 0)
{
continue; // Parallel
}
final float p = (float) ((doorInst.getA() * x) + (doorInst.getB() * y) + (doorInst.getC() * z) + doorInst.getD()) / (float) dk;
final int fx = (int) (x - (l * p));
final int fy = (int) (y - (m * p));
final int fz = (int) (z - (n * p));
if (((Math.min(x, tx) <= fx) && (fx <= Math.max(x, tx))) && ((Math.min(y, ty) <= fy) && (fy <= Math.max(y, ty))) && ((Math.min(z, tz) <= fz) && (fz <= Math.max(z, tz))))
{
if ((((fx >= px1) && (fx <= px2)) || ((fx >= px2) && (fx <= px1))) && (((fy >= py1) && (fy <= py2)) || ((fy >= py2) && (fy <= py1))) && (((fz >= pz1) && (fz <= pz2)) || ((fz >= pz2) && (fz <= pz1))))
{
return true; // Door between
}
}
}
}
}
}
return false;
}
}

View File

@@ -0,0 +1,179 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.io.File;
import java.util.Scanner;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2ExtractableItem;
import com.l2jmobius.gameserver.model.L2ExtractableProductItem;
import javolution.util.FastList;
import javolution.util.FastMap;
/**
* @author FBIagent
*/
public class ExtractableItemsData
{
private final FastMap<Integer, L2ExtractableItem> _items;
private static ExtractableItemsData _instance = null;
public static ExtractableItemsData getInstance()
{
if (_instance == null)
{
_instance = new ExtractableItemsData();
}
return _instance;
}
public ExtractableItemsData()
{
_items = new FastMap<>();
try (Scanner s = new Scanner(new File(Config.DATAPACK_ROOT + "/data/extractable_items.csv")))
{
int lineCount = 0;
while (s.hasNextLine())
{
lineCount++;
final String line = s.nextLine();
if (line.startsWith("#"))
{
continue;
}
if (line.isEmpty())
{
continue;
}
final String[] lineSplit = line.split(";");
boolean ok = true;
int itemID = 0;
try
{
itemID = Integer.parseInt(lineSplit[0]);
}
catch (final Exception e)
{
System.out.println("Extractable items data: Error in line " + lineCount + " -> invalid item id or wrong seperator after item id!");
System.out.println(" " + line);
ok = false;
}
if (!ok)
{
continue;
}
final FastList<L2ExtractableProductItem> product_temp = new FastList<>();
for (int i = 0; i < (lineSplit.length - 1); i++)
{
ok = true;
final String[] lineSplit2 = lineSplit[i + 1].split(",");
if (lineSplit2.length != 3)
{
System.out.println("Extractable items data: Error in line " + lineCount + " -> wrong seperator!");
System.out.println(" " + line);
ok = false;
}
if (!ok)
{
continue;
}
int production = 0, amount = 0, chance = 0;
try
{
production = Integer.parseInt(lineSplit2[0]);
amount = Integer.parseInt(lineSplit2[1]);
chance = Integer.parseInt(lineSplit2[2]);
}
catch (final Exception e)
{
System.out.println("Extractable items data: Error in line " + lineCount + " -> incomplete/invalid production data or wrong seperator!");
System.out.println(" " + line);
ok = false;
}
if (!ok)
{
continue;
}
final L2ExtractableProductItem product = new L2ExtractableProductItem(production, amount, chance);
product_temp.add(product);
}
int fullChances = 0;
for (final L2ExtractableProductItem Pi : product_temp)
{
fullChances += Pi.getChance();
}
if (fullChances > 100)
{
System.out.println("Extractable items data: Error in line " + lineCount + " -> all chances together are more then 100!");
System.out.println(" " + line);
continue;
}
final L2ExtractableItem product = new L2ExtractableItem(itemID, product_temp);
_items.put(itemID, product);
}
System.out.println("Extractable items data: Loaded " + _items.size() + " extractable items!");
}
catch (final Exception e)
{
System.out.println("Extractable items data: Cannot find '" + Config.DATAPACK_ROOT + "/data/extractable_items.csv'");
}
}
public L2ExtractableItem getExtractableItem(int itemID)
{
return _items.get(itemID);
}
public int[] itemIDs()
{
final int size = _items.size();
final int[] result = new int[size];
int i = 0;
for (final L2ExtractableItem ei : _items.values())
{
result[i] = ei.getItemId();
i++;
}
return result;
}
}

View File

@@ -0,0 +1,142 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.FishData;
import javolution.util.FastList;
/**
* @author -Nemesiss-
*/
public class FishTable
{
private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
private static final FishTable _instance = new FishTable();
private static List<FishData> _Fishs;
private static List<FishData> _Fishs_Newbie;
public static FishTable getInstance()
{
return _instance;
}
private FishTable()
{
// Create table that contains all fish data
int count = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id, level, name, hp, hpregen, fish_type, fish_group, fish_guts, guts_check_time, wait_time, combat_time FROM fish ORDER BY id");
ResultSet Fishes = statement.executeQuery())
{
_Fishs_Newbie = new FastList<>();
_Fishs = new FastList<>();
FishData fish;
while (Fishes.next())
{
final int id = Fishes.getInt("id");
final int lvl = Fishes.getInt("level");
final String name = Fishes.getString("name");
final int hp = Fishes.getInt("hp");
final int hpreg = Fishes.getInt("hpregen");
final int type = Fishes.getInt("fish_type");
final int group = Fishes.getInt("fish_group");
final int fish_guts = Fishes.getInt("fish_guts");
final int guts_check_time = Fishes.getInt("guts_check_time");
final int wait_time = Fishes.getInt("wait_time");
final int combat_time = Fishes.getInt("combat_time");
fish = new FishData(id, lvl, name, hp, hpreg, type, group, fish_guts, guts_check_time, wait_time, combat_time);
if (fish.getGroup() == 0)
{
_Fishs_Newbie.add(fish);
}
else
{
_Fishs.add(fish);
}
}
count = _Fishs_Newbie.size() + _Fishs.size();
}
catch (final Exception e)
{
_log.log(Level.SEVERE, "error while creating fishes table" + e);
}
_log.config("FishTable: Loaded " + count + " Fishes.");
}
/**
* @param lvl
* @param type
* @param group
* @return List of Fish that can be fished
*/
public List<FishData> getfish(int lvl, int type, int group)
{
final List<FishData> result = new FastList<>();
List<FishData> _Fishing = null;
if (group == 0)
{
_Fishing = _Fishs_Newbie;
}
else
{
_Fishing = _Fishs;
}
if ((_Fishing == null) || _Fishing.isEmpty())
{
// the fish list is empty
_log.warning("Fish are not defined!");
return null;
}
for (final FishData f : _Fishing)
{
if (f.getLevel() != lvl)
{
continue;
}
if (f.getType() != type)
{
continue;
}
result.add(f);
}
if (result.size() == 0)
{
_log.warning("Cant Find Any Fish!? - Lvl: " + lvl + " Type: " + type);
}
return result;
}
}

View File

@@ -0,0 +1,184 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import javolution.util.FastList;
import javolution.util.FastMap;
/**
* This class stores references to all online game masters. (access level > 100)
* @version $Revision: 1.2.2.1.2.7 $ $Date: 2005/04/05 19:41:24 $
*/
public class GmListTable
{
private static Logger _log = Logger.getLogger(GmListTable.class.getName());
private static GmListTable _instance;
/** List(L2PcInstance>) containing all the GM in game */
private final FastMap<L2PcInstance, Boolean> _gmList;
public static GmListTable getInstance()
{
if (_instance == null)
{
_instance = new GmListTable();
}
return _instance;
}
public FastList<L2PcInstance> getAllGms(boolean includeHidden)
{
final FastList<L2PcInstance> tmpGmList = new FastList<>();
for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext()) != end;)
{
if (includeHidden || !n.getValue())
{
tmpGmList.add(n.getKey());
}
}
return tmpGmList;
}
public FastList<String> getAllGmNames(boolean includeHidden)
{
final FastList<String> tmpGmList = new FastList<>();
for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext()) != end;)
{
if (!n.getValue())
{
tmpGmList.add(n.getKey().getName());
}
else if (includeHidden)
{
tmpGmList.add(n.getKey().getName() + " (invis)");
}
}
return tmpGmList;
}
private GmListTable()
{
_gmList = new FastMap<L2PcInstance, Boolean>().shared();
}
/**
* Add a L2PcInstance player to the Set _gmList
* @param player
* @param hidden
*/
public void addGm(L2PcInstance player, boolean hidden)
{
if (Config.DEBUG)
{
_log.fine("added gm: " + player.getName());
}
_gmList.put(player, hidden);
}
public void deleteGm(L2PcInstance player)
{
if (Config.DEBUG)
{
_log.fine("deleted gm: " + player.getName());
}
_gmList.remove(player);
}
/**
* GM will be displayed on clients gmlist
* @param player
*/
public void showGm(L2PcInstance player)
{
final FastMap.Entry<L2PcInstance, Boolean> gm = _gmList.getEntry(player);
if (gm != null)
{
gm.setValue(false);
}
}
/**
* GM will no longer be displayed on clients gmlist
* @param player
*/
public void hideGm(L2PcInstance player)
{
final FastMap.Entry<L2PcInstance, Boolean> gm = _gmList.getEntry(player);
if (gm != null)
{
gm.setValue(true);
}
}
public boolean isGmOnline(boolean includeHidden)
{
for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext()) != end;)
{
if (includeHidden || !n.getValue())
{
return true;
}
}
return false;
}
public void sendListToPlayer(L2PcInstance player)
{
if (!isGmOnline(player.isGM()))
{
player.sendPacket(new SystemMessage(SystemMessage.NO_GM_PROVIDING_SERVICE_NOW)); // There are not any GMs that are providing customer service currently.
}
else
{
SystemMessage sm = new SystemMessage(SystemMessage.GM_LIST);
player.sendPacket(sm);
for (final String name : getAllGmNames(player.isGM()))
{
sm = new SystemMessage(SystemMessage.GM_S1);
sm.addString(name);
player.sendPacket(sm);
}
}
}
public static void broadcastToGMs(L2GameServerPacket packet)
{
for (final L2PcInstance gm : getInstance().getAllGms(true))
{
gm.sendPacket(packet);
}
}
public static void broadcastMessageToGMs(String message)
{
for (final L2PcInstance gm : getInstance().getAllGms(true))
{
gm.sendPacket(SystemMessage.sendString(message));
}
}
}

View File

@@ -0,0 +1,230 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.templates.L2HelperBuff;
import com.l2jmobius.gameserver.templates.StatsSet;
import javolution.util.FastList;
/**
* This class represents the Newbie Helper Buff list Author: Ayor
*/
public class HelperBuffTable
{
private static Logger _log = Logger.getLogger(HennaTable.class.getName());
private static HelperBuffTable _instance;
/** The table containing all Buff of the Newbie Helper */
private final List<L2HelperBuff> _helperBuff;
private final boolean _initialized = true;
/**
* The player level since Newbie Helper can give the fisrt buff <BR>
* Used to generate message : "Come back here when you have reached level ...")
*/
private int _magicClassLowestLevel = 100;
private int _physicClassLowestLevel = 100;
/**
* The player level above which Newbie Helper won't give any buff <BR>
* Used to generate message : "Only novice character of level ... or less can receive my support magic.")
*/
private int _magicClassHighestLevel = 1;
private int _physicClassHighestLevel = 1;
public static HelperBuffTable getInstance()
{
if (_instance == null)
{
_instance = new HelperBuffTable();
}
return _instance;
}
/**
* Create and Load the Newbie Helper Buff list from SQL Table helper_buff_list
*/
private HelperBuffTable()
{
_helperBuff = new FastList<>();
RestoreHelperBuffData();
}
/**
* Read and Load the Newbie Helper Buff list from SQL Table helper_buff_list
*/
private void RestoreHelperBuffData()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM helper_buff_list");
ResultSet helperbuffdata = statement.executeQuery())
{
fillHelperBuffTable(helperbuffdata);
}
catch (final Exception e)
{
_log.severe("Table helper_buff_list not found : Update your DataPack" + e);
e.printStackTrace();
}
}
/**
* Load the Newbie Helper Buff list from SQL Table helper_buff_list
* @param HelperBuffData
* @throws Exception
*/
private void fillHelperBuffTable(ResultSet HelperBuffData) throws Exception
{
while (HelperBuffData.next())
{
final StatsSet helperBuffDat = new StatsSet();
final int id = HelperBuffData.getInt("id");
helperBuffDat.set("id", id);
helperBuffDat.set("skillID", HelperBuffData.getInt("skill_id"));
helperBuffDat.set("skillLevel", HelperBuffData.getInt("skill_level"));
helperBuffDat.set("lowerLevel", HelperBuffData.getInt("lower_level"));
helperBuffDat.set("upperLevel", HelperBuffData.getInt("upper_level"));
helperBuffDat.set("isMagicClass", HelperBuffData.getString("is_magic_class"));
// Calulate the range level in wich player must be to obtain buff from Newbie Helper
if ("false".equals(HelperBuffData.getString("is_magic_class")))
{
if (HelperBuffData.getInt("lower_level") < _physicClassLowestLevel)
{
_physicClassLowestLevel = HelperBuffData.getInt("lower_level");
}
if (HelperBuffData.getInt("upper_level") > _physicClassHighestLevel)
{
_physicClassHighestLevel = HelperBuffData.getInt("upper_level");
}
}
else
{
if (HelperBuffData.getInt("lower_level") < _magicClassLowestLevel)
{
_magicClassLowestLevel = HelperBuffData.getInt("lower_level");
}
if (HelperBuffData.getInt("upper_level") > _magicClassHighestLevel)
{
_magicClassHighestLevel = HelperBuffData.getInt("upper_level");
}
}
// Add this Helper Buff to the Helper Buff List
final L2HelperBuff template = new L2HelperBuff(helperBuffDat);
_helperBuff.add(template);
}
_log.config("Helper Buff Table: Loaded " + _helperBuff.size() + " Templates.");
}
public boolean isInitialized()
{
return _initialized;
}
public L2HelperBuff getHelperBuffTableItem(int id)
{
return _helperBuff.get(id);
}
/**
* Return the Helper Buff List
* @return
*/
public List<L2HelperBuff> getHelperBuffTable()
{
return _helperBuff;
}
/**
* @return Returns the magicClassHighestLevel.
*/
public int getMagicClassHighestLevel()
{
return _magicClassHighestLevel;
}
/**
* @param magicClassHighestLevel The magicClassHighestLevel to set.
*/
public void setMagicClassHighestLevel(int magicClassHighestLevel)
{
_magicClassHighestLevel = magicClassHighestLevel;
}
/**
* @return Returns the magicClassLowestLevel.
*/
public int getMagicClassLowestLevel()
{
return _magicClassLowestLevel;
}
/**
* @param magicClassLowestLevel The magicClassLowestLevel to set.
*/
public void setMagicClassLowestLevel(int magicClassLowestLevel)
{
_magicClassLowestLevel = magicClassLowestLevel;
}
/**
* @return Returns the physicClassHighestLevel.
*/
public int getPhysicClassHighestLevel()
{
return _physicClassHighestLevel;
}
/**
* @param physicClassHighestLevel The physicClassHighestLevel to set.
*/
public void setPhysicClassHighestLevel(int physicClassHighestLevel)
{
_physicClassHighestLevel = physicClassHighestLevel;
}
/**
* @return Returns the physicClassLowestLevel.
*/
public int getPhysicClassLowestLevel()
{
return _physicClassLowestLevel;
}
/**
* @param physicClassLowestLevel The physicClassLowestLevel to set.
*/
public void setPhysicClassLowestLevel(int physicClassLowestLevel)
{
_physicClassLowestLevel = physicClassLowestLevel;
}
}

View File

@@ -0,0 +1,112 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.templates.L2Henna;
import com.l2jmobius.gameserver.templates.StatsSet;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision$ $Date$
*/
public class HennaTable
{
private static Logger _log = Logger.getLogger(HennaTable.class.getName());
private static HennaTable _instance;
private final Map<Integer, L2Henna> _henna;
private final boolean _initialized = true;
public static HennaTable getInstance()
{
if (_instance == null)
{
_instance = new HennaTable();
}
return _instance;
}
private HennaTable()
{
_henna = new FastMap<>();
RestoreHennaData();
}
/**
*
*/
private void RestoreHennaData()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT symbol_id, symbol_name, dye_id, dye_amount, price, stat_INT, stat_STR, stat_CON, stat_MEN, stat_DEX, stat_WIT FROM henna");
ResultSet hennadata = statement.executeQuery())
{
fillHennaTable(hennadata);
}
catch (final Exception e)
{
_log.severe("error while creating henna table " + e);
e.printStackTrace();
}
}
private void fillHennaTable(ResultSet HennaData) throws Exception
{
while (HennaData.next())
{
final StatsSet hennaDat = new StatsSet();
final int id = HennaData.getInt("symbol_id");
hennaDat.set("symbol_id", id);
// hennaDat.set("symbol_name", HennaData.getString("symbol_name"));
hennaDat.set("dye", HennaData.getInt("dye_id"));
hennaDat.set("price", HennaData.getInt("price"));
// amount of dye required
hennaDat.set("amount", HennaData.getInt("dye_amount"));
hennaDat.set("stat_INT", HennaData.getInt("stat_INT"));
hennaDat.set("stat_STR", HennaData.getInt("stat_STR"));
hennaDat.set("stat_CON", HennaData.getInt("stat_CON"));
hennaDat.set("stat_MEN", HennaData.getInt("stat_MEN"));
hennaDat.set("stat_DEX", HennaData.getInt("stat_DEX"));
hennaDat.set("stat_WIT", HennaData.getInt("stat_WIT"));
final L2Henna template = new L2Henna(hennaDat);
_henna.put(id, template);
}
_log.config("HennaTable: Loaded " + _henna.size() + " Templates.");
}
public boolean isInitialized()
{
return _initialized;
}
public L2Henna getTemplate(int id)
{
return _henna.get(id);
}
}

View File

@@ -0,0 +1,136 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2HennaInstance;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.templates.L2Henna;
import javolution.util.FastList;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision$ $Date$
*/
public class HennaTreeTable
{
private static Logger _log = Logger.getLogger(HennaTreeTable.class.getName());
private static final HennaTreeTable _instance = new HennaTreeTable();
private final Map<ClassId, List<L2HennaInstance>> _hennaTrees;
private final boolean _initialized = true;
public static HennaTreeTable getInstance()
{
return _instance;
}
private HennaTreeTable()
{
_hennaTrees = new FastMap<>();
int classId = 0;
int count = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT class_name, id, parent_id FROM class_list ORDER BY id");
ResultSet classlist = statement.executeQuery())
{
List<L2HennaInstance> list;
while (classlist.next())
{
list = new FastList<>();
classId = classlist.getInt("id");
try (PreparedStatement statement2 = con.prepareStatement("SELECT class_id, symbol_id FROM henna_trees where class_id=? ORDER BY symbol_id"))
{
statement2.setInt(1, classId);
try (ResultSet hennatree = statement2.executeQuery())
{
while (hennatree.next())
{
final int id = hennatree.getInt("symbol_id");
final L2Henna template = HennaTable.getInstance().getTemplate(id);
if (template == null)
{
continue;
}
final L2HennaInstance temp = new L2HennaInstance(template);
temp.setSymbolId(id);
temp.setItemIdDye(template.getDyeId());
temp.setAmountDyeRequire(template.getAmountDyeRequire());
temp.setPrice(template.getPrice());
temp.setStatINT(template.getStatINT());
temp.setStatSTR(template.getStatSTR());
temp.setStatCON(template.getStatCON());
temp.setStatMEN(template.getStatMEN());
temp.setStatDEX(template.getStatDEX());
temp.setStatWIT(template.getStatWIT());
list.add(temp);
}
}
}
_hennaTrees.put(ClassId.values()[classId], list);
count += list.size();
_log.fine("Henna Tree for Class: " + classId + " has " + list.size() + " Henna Templates.");
}
}
catch (final Exception e)
{
_log.warning("error while creating henna tree for classId " + classId + " " + e);
e.printStackTrace();
}
_log.config("HennaTreeTable: Loaded " + count + " Henna Tree Templates.");
}
public L2HennaInstance[] getAvailableHenna(ClassId classId)
{
final List<L2HennaInstance> result = new FastList<>();
final List<L2HennaInstance> henna = _hennaTrees.get(classId);
if (henna == null)
{
// the hennatree for this class is undefined, so we give an empty list
_log.warning("Hennatree for class " + classId + " is not defined!");
return new L2HennaInstance[0];
}
for (int i = 0; i < henna.size(); i++)
{
final L2HennaInstance temp = henna.get(i);
result.add(temp);
}
return result.toArray(new L2HennaInstance[result.size()]);
}
public boolean isInitialized()
{
return _initialized;
}
}

View File

@@ -0,0 +1,878 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.Item;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.model.L2Attackable;
import com.l2jmobius.gameserver.model.L2ItemInstance;
import com.l2jmobius.gameserver.model.L2ItemInstance.ItemLocation;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2PetDataTable;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.skills.SkillsEngine;
import com.l2jmobius.gameserver.templates.L2Armor;
import com.l2jmobius.gameserver.templates.L2ArmorType;
import com.l2jmobius.gameserver.templates.L2EtcItem;
import com.l2jmobius.gameserver.templates.L2EtcItemType;
import com.l2jmobius.gameserver.templates.L2Item;
import com.l2jmobius.gameserver.templates.L2Weapon;
import com.l2jmobius.gameserver.templates.L2WeaponType;
import com.l2jmobius.gameserver.templates.StatsSet;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.9.2.6.2.9 $ $Date: 2005/04/02 15:57:34 $
*/
public class ItemTable
{
private static Logger _log = Logger.getLogger(ItemTable.class.getName());
private static Logger _logItems = Logger.getLogger("item");
private static final Map<String, Integer> _materials = new FastMap<>();
private static final Map<String, Integer> _crystalTypes = new FastMap<>();
private static final Map<String, L2WeaponType> _weaponTypes = new FastMap<>();
private static final Map<String, L2ArmorType> _armorTypes = new FastMap<>();
private static final Map<String, Integer> _slots = new FastMap<>();
private L2Item[] _allTemplates;
private final Map<Integer, L2EtcItem> _etcItems;
private final Map<Integer, L2Armor> _armors;
private final Map<Integer, L2Weapon> _weapons;
private final boolean _initialized = true;
static
{
_materials.put("paper", L2Item.MATERIAL_PAPER);
_materials.put("wood", L2Item.MATERIAL_WOOD);
_materials.put("liquid", L2Item.MATERIAL_LIQUID);
_materials.put("cloth", L2Item.MATERIAL_CLOTH);
_materials.put("leather", L2Item.MATERIAL_LEATHER);
_materials.put("horn", L2Item.MATERIAL_HORN);
_materials.put("bone", L2Item.MATERIAL_BONE);
_materials.put("bronze", L2Item.MATERIAL_BRONZE);
_materials.put("fine_steel", L2Item.MATERIAL_FINE_STEEL);
_materials.put("cotton", L2Item.MATERIAL_FINE_STEEL);
_materials.put("mithril", L2Item.MATERIAL_MITHRIL);
_materials.put("silver", L2Item.MATERIAL_SILVER);
_materials.put("gold", L2Item.MATERIAL_GOLD);
_materials.put("adamantaite", L2Item.MATERIAL_ADAMANTAITE);
_materials.put("steel", L2Item.MATERIAL_STEEL);
_materials.put("oriharukon", L2Item.MATERIAL_ORIHARUKON);
_materials.put("blood_steel", L2Item.MATERIAL_BLOOD_STEEL);
_materials.put("crystal", L2Item.MATERIAL_CRYSTAL);
_materials.put("damascus", L2Item.MATERIAL_DAMASCUS);
_materials.put("chrysolite", L2Item.MATERIAL_CHRYSOLITE);
_materials.put("scale_of_dragon", L2Item.MATERIAL_SCALE_OF_DRAGON);
_materials.put("dyestuff", L2Item.MATERIAL_DYESTUFF);
_materials.put("cobweb", L2Item.MATERIAL_COBWEB);
_materials.put("seed", L2Item.MATERIAL_SEED);
_crystalTypes.put("s", L2Item.CRYSTAL_S);
_crystalTypes.put("a", L2Item.CRYSTAL_A);
_crystalTypes.put("b", L2Item.CRYSTAL_B);
_crystalTypes.put("c", L2Item.CRYSTAL_C);
_crystalTypes.put("d", L2Item.CRYSTAL_D);
_crystalTypes.put("none", L2Item.CRYSTAL_NONE);
_weaponTypes.put("blunt", L2WeaponType.BLUNT);
_weaponTypes.put("bow", L2WeaponType.BOW);
_weaponTypes.put("dagger", L2WeaponType.DAGGER);
_weaponTypes.put("dual", L2WeaponType.DUAL);
_weaponTypes.put("dualfist", L2WeaponType.DUALFIST);
_weaponTypes.put("etc", L2WeaponType.ETC);
_weaponTypes.put("fist", L2WeaponType.FIST);
_weaponTypes.put("none", L2WeaponType.NONE); // these are shields !
_weaponTypes.put("pole", L2WeaponType.POLE);
_weaponTypes.put("sword", L2WeaponType.SWORD);
_weaponTypes.put("bigsword", L2WeaponType.BIGSWORD); // Two-Handed Swords
_weaponTypes.put("pet", L2WeaponType.PET); // Pet Weapon
_weaponTypes.put("rod", L2WeaponType.ROD); // Fishing Rods
_weaponTypes.put("bigblunt", L2WeaponType.BIGBLUNT); // Two handed blunt
_armorTypes.put("none", L2ArmorType.NONE);
_armorTypes.put("light", L2ArmorType.LIGHT);
_armorTypes.put("heavy", L2ArmorType.HEAVY);
_armorTypes.put("magic", L2ArmorType.MAGIC);
_armorTypes.put("pet", L2ArmorType.PET);
_slots.put("chest", L2Item.SLOT_CHEST);
_slots.put("fullarmor", L2Item.SLOT_FULL_ARMOR);
_slots.put("head", L2Item.SLOT_HEAD);
_slots.put("hair", L2Item.SLOT_HAIR);
_slots.put("underwear", L2Item.SLOT_UNDERWEAR);
_slots.put("back", L2Item.SLOT_BACK);
_slots.put("neck", L2Item.SLOT_NECK);
_slots.put("legs", L2Item.SLOT_LEGS);
_slots.put("feet", L2Item.SLOT_FEET);
_slots.put("gloves", L2Item.SLOT_GLOVES);
_slots.put("chest,legs", L2Item.SLOT_CHEST | L2Item.SLOT_LEGS);
_slots.put("rhand", L2Item.SLOT_R_HAND);
_slots.put("lhand", L2Item.SLOT_L_HAND);
_slots.put("lrhand", L2Item.SLOT_LR_HAND);
_slots.put("rear,lear", L2Item.SLOT_R_EAR | L2Item.SLOT_L_EAR);
_slots.put("rfinger,lfinger", L2Item.SLOT_R_FINGER | L2Item.SLOT_L_FINGER);
_slots.put("none", L2Item.SLOT_NONE);
_slots.put("wolf", L2Item.SLOT_WOLF); // for wolf
_slots.put("hatchling", L2Item.SLOT_HATCHLING); // for hatchling
_slots.put("strider", L2Item.SLOT_STRIDER); // for strider
}
private static ItemTable _instance;
/** Table of SQL request in order to obtain items from tables [etcitem], [armor], [weapon] */
private static final String[] SQL_ITEM_SELECTS =
{
"SELECT item_id, name, crystallizable, item_type, weight, consume_type, material, crystal_type, price, crystal_count, sellable, dropable, destroyable, tradeable FROM etcitem",
"SELECT item_id, name, bodypart, crystallizable, armor_type, weight, material, crystal_type, avoid_modify, p_def, m_def, mp_bonus, price, crystal_count, sellable, dropable, destroyable, tradeable, item_skill_id, item_skill_lvl FROM armor",
"SELECT item_id, name, bodypart, crystallizable, weight, soulshots, spiritshots, material, crystal_type, p_dam, rnd_dam, weaponType, critical, hit_modify, avoid_modify, shield_def, shield_def_rate, atk_speed, mp_consume," + " m_dam, price, crystal_count, sellable, dropable, destroyable, tradeable, item_skill_id, item_skill_lvl, onCast_skill_id, onCast_skill_lvl, onCast_skill_chance, onCrit_skill_id, onCrit_skill_lvl, onCrit_skill_chance FROM weapon"
};
/** Table of SQL request in order to obtain items from tables [custom_etcitem], [custom_armor], [custom_weapon] */
private static final String[] SQL_CUSTOM_ITEM_SELECTS =
{
"SELECT item_id, name, crystallizable, item_type, weight, consume_type, material, crystal_type, price, crystal_count, sellable, dropable, destroyable, tradeable FROM custom_etcitem",
"SELECT item_id, name, bodypart, crystallizable, armor_type, weight, material, crystal_type, avoid_modify, p_def, m_def, mp_bonus, price, crystal_count, sellable, dropable, destroyable, tradeable, item_skill_id, item_skill_lvl FROM custom_armor",
"SELECT item_id, name, bodypart, crystallizable, weight, soulshots, spiritshots, material, crystal_type, p_dam, rnd_dam, weaponType, critical, hit_modify, avoid_modify, shield_def, shield_def_rate, atk_speed, mp_consume," + " m_dam, price, crystal_count, sellable, dropable, destroyable, tradeable, item_skill_id, item_skill_lvl, onCast_skill_id, onCast_skill_lvl, onCast_skill_chance, onCrit_skill_id, onCrit_skill_lvl, onCrit_skill_chance FROM custom_weapon"
};
/** List of etcItem */
private static final Map<Integer, Item> itemData = new FastMap<>();
/** List of weapons */
private static final Map<Integer, Item> weaponData = new FastMap<>();
/** List of armor */
private static final Map<Integer, Item> armorData = new FastMap<>();
/**
* Returns instance of ItemTable
* @return ItemTable
*/
public static ItemTable getInstance()
{
if (_instance == null)
{
_instance = new ItemTable();
}
return _instance;
}
/**
* Returns a new object Item
* @return
*/
public Item newItem()
{
return new Item();
}
/**
* Constructor.
*/
public ItemTable()
{
_etcItems = new FastMap<>();
_armors = new FastMap<>();
_weapons = new FastMap<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
for (final String selectQuery : SQL_ITEM_SELECTS)
{
try (PreparedStatement statement = con.prepareStatement(selectQuery);
ResultSet rset = statement.executeQuery())
{
// Add item in correct FastMap
while (rset.next())
{
if (selectQuery.endsWith("etcitem"))
{
final Item newItem = readItem(rset);
itemData.put(newItem.id, newItem);
}
else if (selectQuery.endsWith("armor"))
{
final Item newItem = readArmor(rset);
armorData.put(newItem.id, newItem);
}
else if (selectQuery.endsWith("weapon"))
{
final Item newItem = readWeapon(rset);
weaponData.put(newItem.id, newItem);
}
}
}
}
}
catch (final Exception e)
{
_log.log(Level.WARNING, "data error on item: ", e);
}
if (Config.CUSTOM_ITEM_TABLES)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
for (final String selectQuery : SQL_CUSTOM_ITEM_SELECTS)
{
try (PreparedStatement statement = con.prepareStatement(selectQuery);
ResultSet rset = statement.executeQuery())
{
// Add item in correct FastMap
while (rset.next())
{
if (selectQuery.endsWith("etcitem"))
{
final Item newItem = readItem(rset);
if (itemData.containsKey(newItem.id))
{
itemData.remove(newItem.id);
}
itemData.put(newItem.id, newItem);
}
else if (selectQuery.endsWith("armor"))
{
final Item newItem = readArmor(rset);
if (armorData.containsKey(newItem.id))
{
armorData.remove(newItem.id);
}
armorData.put(newItem.id, newItem);
}
else if (selectQuery.endsWith("weapon"))
{
final Item newItem = readWeapon(rset);
if (weaponData.containsKey(newItem.id))
{
weaponData.remove(newItem.id);
}
weaponData.put(newItem.id, newItem);
}
}
}
}
}
catch (final Exception e)
{
_log.log(Level.WARNING, "data error on custom item: ", e);
}
}
for (final L2Armor armor : SkillsEngine.getInstance().loadArmors(armorData))
{
_armors.put(armor.getItemId(), armor);
}
_log.config("ItemTable: Loaded " + _armors.size() + " Armors.");
for (final L2EtcItem item : SkillsEngine.getInstance().loadItems(itemData))
{
_etcItems.put(item.getItemId(), item);
}
_log.config("ItemTable: Loaded " + _etcItems.size() + " Items.");
for (final L2Weapon weapon : SkillsEngine.getInstance().loadWeapons(weaponData))
{
_weapons.put(weapon.getItemId(), weapon);
}
_log.config("ItemTable: Loaded " + _weapons.size() + " Weapons.");
buildFastLookupTable();
}
/**
* Returns object Item from the record of the database
* @param rset : ResultSet designating a record of the [weapon] table of database
* @return Item : object created from the database record
* @throws SQLException
*/
private Item readWeapon(ResultSet rset) throws SQLException
{
final Item item = new Item();
item.set = new StatsSet();
item.type = _weaponTypes.get(rset.getString("weaponType"));
item.id = rset.getInt("item_id");
item.name = rset.getString("name");
item.set.set("item_id", item.id);
item.set.set("name", item.name);
// lets see if this is a shield
if (item.type == L2WeaponType.NONE)
{
item.set.set("type1", L2Item.TYPE1_SHIELD_ARMOR);
item.set.set("type2", L2Item.TYPE2_SHIELD_ARMOR);
}
else
{
item.set.set("type1", L2Item.TYPE1_WEAPON_RING_EARRING_NECKLACE);
item.set.set("type2", L2Item.TYPE2_WEAPON);
}
item.set.set("bodypart", _slots.get(rset.getString("bodypart")));
item.set.set("material", _materials.get(rset.getString("material")));
item.set.set("crystal_type", _crystalTypes.get(rset.getString("crystal_type")));
item.set.set("crystallizable", Boolean.valueOf(rset.getString("crystallizable")).booleanValue());
item.set.set("weight", rset.getInt("weight"));
item.set.set("soulshots", rset.getInt("soulshots"));
item.set.set("spiritshots", rset.getInt("spiritshots"));
item.set.set("p_dam", rset.getInt("p_dam"));
item.set.set("rnd_dam", rset.getInt("rnd_dam"));
item.set.set("critical", rset.getInt("critical"));
item.set.set("hit_modify", rset.getDouble("hit_modify"));
item.set.set("avoid_modify", rset.getInt("avoid_modify"));
item.set.set("shield_def", rset.getInt("shield_def"));
item.set.set("shield_def_rate", rset.getInt("shield_def_rate"));
item.set.set("atk_speed", rset.getInt("atk_speed"));
item.set.set("mp_consume", rset.getInt("mp_consume"));
item.set.set("m_dam", rset.getInt("m_dam"));
item.set.set("price", rset.getInt("price"));
item.set.set("crystal_count", rset.getInt("crystal_count"));
item.set.set("sellable", Boolean.valueOf(rset.getString("sellable")));
item.set.set("dropable", Boolean.valueOf(rset.getString("dropable")));
item.set.set("destroyable", Boolean.valueOf(rset.getString("destroyable")));
item.set.set("tradeable", Boolean.valueOf(rset.getString("tradeable")));
item.set.set("item_skill_id", rset.getInt("item_skill_id"));
item.set.set("item_skill_lvl", rset.getInt("item_skill_lvl"));
item.set.set("onCast_skill_id", rset.getInt("onCast_skill_id"));
item.set.set("onCast_skill_lvl", rset.getInt("onCast_skill_lvl"));
item.set.set("onCast_skill_chance", rset.getInt("onCast_skill_chance"));
item.set.set("onCrit_skill_id", rset.getInt("onCrit_skill_id"));
item.set.set("onCrit_skill_lvl", rset.getInt("onCrit_skill_lvl"));
item.set.set("onCrit_skill_chance", rset.getInt("onCrit_skill_chance"));
if (item.type == L2WeaponType.PET)
{
item.set.set("type1", L2Item.TYPE1_WEAPON_RING_EARRING_NECKLACE);
if (item.set.getInteger("bodypart") == L2Item.SLOT_WOLF)
{
item.set.set("type2", L2Item.TYPE2_PET_WOLF);
}
else if (item.set.getInteger("bodypart") == L2Item.SLOT_HATCHLING)
{
item.set.set("type2", L2Item.TYPE2_PET_HATCHLING);
}
else
{
item.set.set("type2", L2Item.TYPE2_PET_STRIDER);
}
item.set.set("bodypart", L2Item.SLOT_R_HAND);
}
return item;
}
/**
* Returns object Item from the record of the database
* @param rset : ResultSet designating a record of the [armor] table of database
* @return Item : object created from the database record
* @throws SQLException
*/
private Item readArmor(ResultSet rset) throws SQLException
{
final Item item = new Item();
item.set = new StatsSet();
item.type = _armorTypes.get(rset.getString("armor_type"));
item.id = rset.getInt("item_id");
item.name = rset.getString("name");
item.set.set("item_id", item.id);
item.set.set("name", item.name);
final int bodypart = _slots.get(rset.getString("bodypart"));
item.set.set("bodypart", bodypart);
item.set.set("crystallizable", Boolean.valueOf(rset.getString("crystallizable")));
item.set.set("crystal_count", rset.getInt("crystal_count"));
item.set.set("sellable", Boolean.valueOf(rset.getString("sellable")));
item.set.set("dropable", Boolean.valueOf(rset.getString("dropable")));
item.set.set("destroyable", Boolean.valueOf(rset.getString("destroyable")));
item.set.set("tradeable", Boolean.valueOf(rset.getString("tradeable")));
if ((bodypart == L2Item.SLOT_NECK) || (bodypart == L2Item.SLOT_HAIR) || ((bodypart & L2Item.SLOT_L_EAR) != 0) || ((bodypart & L2Item.SLOT_L_FINGER) != 0))
{
item.set.set("type1", L2Item.TYPE1_WEAPON_RING_EARRING_NECKLACE);
item.set.set("type2", L2Item.TYPE2_ACCESSORY);
}
else
{
item.set.set("type1", L2Item.TYPE1_SHIELD_ARMOR);
item.set.set("type2", L2Item.TYPE2_SHIELD_ARMOR);
}
item.set.set("weight", rset.getInt("weight"));
item.set.set("material", _materials.get(rset.getString("material")));
item.set.set("crystal_type", _crystalTypes.get(rset.getString("crystal_type")));
item.set.set("avoid_modify", rset.getInt("avoid_modify"));
item.set.set("p_def", rset.getInt("p_def"));
item.set.set("m_def", rset.getInt("m_def"));
item.set.set("mp_bonus", rset.getInt("mp_bonus"));
item.set.set("price", rset.getInt("price"));
item.set.set("item_skill_id", rset.getInt("item_skill_id"));
item.set.set("item_skill_lvl", rset.getInt("item_skill_lvl"));
if (item.type == L2ArmorType.PET)
{
if (bodypart == L2Item.SLOT_NECK)
{
item.set.set("type1", L2Item.TYPE1_WEAPON_RING_EARRING_NECKLACE);
item.set.set("type2", L2Item.TYPE2_ACCESSORY);
item.set.set("bodypart", L2Item.SLOT_NECK);
}
else
{
item.set.set("type1", L2Item.TYPE1_SHIELD_ARMOR);
switch (item.set.getInteger("bodypart"))
{
case L2Item.SLOT_WOLF:
item.set.set("type2", L2Item.TYPE2_PET_WOLF);
break;
case L2Item.SLOT_HATCHLING:
item.set.set("type2", L2Item.TYPE2_PET_HATCHLING);
break;
default:
item.set.set("type2", L2Item.TYPE2_PET_STRIDER);
break;
}
item.set.set("bodypart", L2Item.SLOT_CHEST);
}
}
return item;
}
/**
* Returns object Item from the record of the database
* @param rset : ResultSet designating a record of the [etcitem] table of database
* @return Item : object created from the database record
* @throws SQLException
*/
private Item readItem(ResultSet rset) throws SQLException
{
final Item item = new Item();
item.set = new StatsSet();
item.id = rset.getInt("item_id");
item.set.set("item_id", item.id);
item.set.set("crystallizable", Boolean.valueOf(rset.getString("crystallizable")));
item.set.set("type1", L2Item.TYPE1_ITEM_QUESTITEM_ADENA);
item.set.set("type2", L2Item.TYPE2_OTHER);
item.set.set("bodypart", 0);
item.set.set("crystal_count", rset.getInt("crystal_count"));
item.set.set("sellable", Boolean.valueOf(rset.getString("sellable")));
item.set.set("dropable", Boolean.valueOf(rset.getString("dropable")));
item.set.set("destroyable", Boolean.valueOf(rset.getString("destroyable")));
item.set.set("tradeable", Boolean.valueOf(rset.getString("tradeable")));
final String itemType = rset.getString("item_type");
if (itemType.equals("none"))
{
item.type = L2EtcItemType.OTHER; // only for default
}
else if (itemType.equals("castle_guard"))
{
item.type = L2EtcItemType.SCROLL; // dummy
}
else if (itemType.equals("material"))
{
item.type = L2EtcItemType.MATERIAL;
}
else if (itemType.equals("pet_collar"))
{
item.type = L2EtcItemType.PET_COLLAR;
}
else if (itemType.equals("potion"))
{
item.type = L2EtcItemType.POTION;
}
else if (itemType.equals("recipe"))
{
item.type = L2EtcItemType.RECEIPE;
}
else if (itemType.equals("scroll"))
{
item.type = L2EtcItemType.SCROLL;
}
else if (itemType.equals("seed"))
{
item.type = L2EtcItemType.SEED;
}
else if (itemType.equals("shot"))
{
item.type = L2EtcItemType.SHOT;
}
else if (itemType.equals("spellbook"))
{
item.type = L2EtcItemType.SPELLBOOK; // Spellbook, Amulet, Blueprint
}
else if (itemType.equals("arrow"))
{
item.type = L2EtcItemType.ARROW;
item.set.set("bodypart", L2Item.SLOT_L_HAND);
}
else if (itemType.equals("quest"))
{
item.type = L2EtcItemType.QUEST;
item.set.set("type2", L2Item.TYPE2_QUEST);
}
else if (itemType.equals("lure"))
{
item.type = L2EtcItemType.OTHER;
item.set.set("bodypart", L2Item.SLOT_L_HAND);
}
else
{
_log.fine("unknown etcitem type:" + itemType);
item.type = L2EtcItemType.OTHER;
}
final String consume = rset.getString("consume_type");
if (consume.equals("asset"))
{
item.type = L2EtcItemType.MONEY;
item.set.set("stackable", true);
item.set.set("type2", L2Item.TYPE2_MONEY);
}
else if (consume.equals("stackable"))
{
item.set.set("stackable", true);
}
else
{
item.set.set("stackable", false);
}
final int material = _materials.get(rset.getString("material"));
item.set.set("material", material);
final int crystal = _crystalTypes.get(rset.getString("crystal_type"));
item.set.set("crystal_type", crystal);
final int weight = rset.getInt("weight");
item.set.set("weight", weight);
item.name = rset.getString("name");
item.set.set("name", item.name);
item.set.set("price", rset.getInt("price"));
return item;
}
/**
* Returns if ItemTable initialized
* @return boolean
*/
public boolean isInitialized()
{
return _initialized;
}
/**
* Builds a variable in which all items are putting in in function of their ID.
*/
private void buildFastLookupTable()
{
int highestId = 0;
// Get highest ID of item in armor FastMap, then in weapon FastMap, and finally in etcitem FastMap
for (final Integer id : _armors.keySet())
{
final L2Armor item = _armors.get(id);
if (item.getItemId() > highestId)
{
highestId = item.getItemId();
}
}
for (final Integer id : _weapons.keySet())
{
final L2Weapon item = _weapons.get(id);
if (item.getItemId() > highestId)
{
highestId = item.getItemId();
}
}
for (final Integer id : _etcItems.keySet())
{
final L2EtcItem item = _etcItems.get(id);
if (item.getItemId() > highestId)
{
highestId = item.getItemId();
}
}
// Create a FastLookUp Table called _allTemplates of size : value of the highest item ID
if (Config.DEBUG)
{
_log.fine("highest item id used:" + highestId);
}
_allTemplates = new L2Item[highestId + 1];
// Insert armor item in Fast Look Up Table
for (final Integer id : _armors.keySet())
{
final L2Armor item = _armors.get(id);
assert _allTemplates[id.intValue()] == null;
_allTemplates[id.intValue()] = item;
}
// Insert weapon item in Fast Look Up Table
for (final Integer id : _weapons.keySet())
{
final L2Weapon item = _weapons.get(id);
assert _allTemplates[id.intValue()] == null;
_allTemplates[id.intValue()] = item;
}
// Insert etcItem item in Fast Look Up Table
for (final Integer id : _etcItems.keySet())
{
final L2EtcItem item = _etcItems.get(id);
assert _allTemplates[id.intValue()] == null;
_allTemplates[id.intValue()] = item;
}
}
/**
* Returns the item corresponding to the item ID
* @param id : int designating the item
* @return L2Item
*/
public L2Item getTemplate(int id)
{
if (id > _allTemplates.length)
{
return null;
}
return _allTemplates[id];
}
/**
* Create the L2ItemInstance corresponding to the Item Identifier and quantitiy add logs the activity.<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Create and Init the L2ItemInstance corresponding to the Item Identifier and quantity</li>
* <li>Add the L2ItemInstance object to _allObjects of L2world</li>
* <li>Logs Item creation according to log settings</li><BR>
* <BR>
* @param process : String Identifier of process triggering this action
* @param itemId : int Item Identifier of the item to be created
* @param count : int Quantity of items to be created for stackable items
* @param actor : L2PcInstance Player requesting the item creation
* @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation
* @return L2ItemInstance corresponding to the new item
*/
public L2ItemInstance createItem(String process, int itemId, int count, L2PcInstance actor, L2Object reference)
{
// Create and Init the L2ItemInstance corresponding to the Item Identifier
final L2ItemInstance item = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
if (process.equalsIgnoreCase("loot"))
{
ScheduledFuture<?> itemLootShedule;
if ((reference != null) && (reference instanceof L2Attackable) && ((L2Attackable) reference).isRaid() && !Config.AUTO_LOOT_RAIDS)
{
item.setOwnerId(actor.getObjectId());
itemLootShedule = ThreadPoolManager.getInstance().scheduleGeneral(new resetOwner(item), 15000);
item.setItemLootSchedule(itemLootShedule);
}
else if (!Config.AUTO_LOOT)
{
item.setOwnerId(actor.getObjectId());
itemLootShedule = ThreadPoolManager.getInstance().scheduleGeneral(new resetOwner(item), 15000);
item.setItemLootSchedule(itemLootShedule);
}
}
if (Config.DEBUG)
{
_log.fine("ItemTable: Item created oid:" + item.getObjectId() + " itemid:" + itemId);
}
// Add the L2ItemInstance object to _allObjects of L2world
L2World.getInstance().storeObject(item);
// Set Item parameters
if (item.isStackable() && (count > 1))
{
item.setCount(count);
}
if (Config.LOG_ITEMS)
{
final LogRecord record = new LogRecord(Level.INFO, "CREATE:" + process);
record.setLoggerName("item");
record.setParameters(new Object[]
{
item,
actor,
reference
});
_logItems.log(record);
}
return item;
}
public L2ItemInstance createItem(String process, int itemId, int count, L2PcInstance actor)
{
return createItem(process, itemId, count, actor, null);
}
/**
* Returns a dummy (fr = factice) item.<BR>
* <BR>
* <U><I>Concept :</I></U><BR>
* Dummy item is created by setting the ID of the object in the world at null value
* @param itemId : int designating the item
* @return L2ItemInstance designating the dummy item created
*/
public L2ItemInstance createDummyItem(int itemId)
{
final L2Item item = getTemplate(itemId);
if (item == null)
{
return null;
}
L2ItemInstance temp = new L2ItemInstance(0, item);
try
{
temp = new L2ItemInstance(0, itemId);
}
catch (final ArrayIndexOutOfBoundsException e)
{
// this can happen if the item templates were not initialized
}
if (temp.getItem() == null)
{
_log.warning("ItemTable: Item Template missing for Id: " + itemId);
}
return temp;
}
/**
* Destroys the L2ItemInstance.<BR>
* <BR>
* <B><U> Actions</U> :</B><BR>
* <BR>
* <li>Sets L2ItemInstance parameters to be unusable</li>
* <li>Removes the L2ItemInstance object to _allObjects of L2world</li>
* <li>Logs Item deletion according to log settings</li><BR>
* <BR>
* @param process : String Identifier of process triggering this action
* @param item : int Item Identifier of the item to be created
* @param actor : L2PcInstance Player requesting the item destroy
* @param reference : L2Object Object referencing current action like NPC selling item or previous item in transformation
*/
public void destroyItem(String process, L2ItemInstance item, L2PcInstance actor, L2Object reference)
{
synchronized (item)
{
item.setCount(0);
item.setOwnerId(0);
item.setLocation(ItemLocation.VOID);
item.setLastChange(L2ItemInstance.REMOVED);
L2World.getInstance().removeObject(item);
IdFactory.getInstance().releaseId(item.getObjectId());
if (Config.LOG_ITEMS)
{
final LogRecord record = new LogRecord(Level.INFO, "DELETE:" + process);
record.setLoggerName("item");
record.setParameters(new Object[]
{
item,
actor,
reference
});
_logItems.log(record);
}
// if it's a pet control item, delete the pet as well
if (L2PetDataTable.isPetItem(item.getItemId()))
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM pets WHERE item_obj_id=?"))
{
// Delete the pet in db
statement.setInt(1, item.getObjectId());
statement.execute();
}
catch (final Exception e)
{
_log.log(Level.WARNING, "could not delete pet objectid:", e);
}
}
}
}
public void reload()
{
synchronized (_instance)
{
_instance = null;
_instance = new ItemTable();
}
}
protected class resetOwner implements Runnable
{
L2ItemInstance _item;
public resetOwner(L2ItemInstance item)
{
_item = item;
}
@Override
public void run()
{
_item.setOwnerId(0);
_item.setItemLootSchedule(null);
}
}
}

View File

@@ -0,0 +1,115 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2LvlupData;
import com.l2jmobius.gameserver.model.base.ClassId;
import javolution.util.FastMap;
/**
* This class ...
* @author NightMarez
* @version $Revision: 1.3.2.4.2.3 $ $Date: 2005/03/27 15:29:18 $
*/
public class LevelUpData
{
private static final String SELECT_ALL = "SELECT classid, defaulthpbase, defaulthpadd, defaulthpmod, defaultcpbase, defaultcpadd, defaultcpmod, defaultmpbase, defaultmpadd, defaultmpmod, class_lvl FROM lvlupgain";
private static final String CLASS_LVL = "class_lvl";
private static final String MP_MOD = "defaultmpmod";
private static final String MP_ADD = "defaultmpadd";
private static final String MP_BASE = "defaultmpbase";
private static final String HP_MOD = "defaulthpmod";
private static final String HP_ADD = "defaulthpadd";
private static final String HP_BASE = "defaulthpbase";
private static final String CP_MOD = "defaultcpmod";
private static final String CP_ADD = "defaultcpadd";
private static final String CP_BASE = "defaultcpbase";
private static final String CLASS_ID = "classid";
private static Logger _log = Logger.getLogger(LevelUpData.class.getName());
private static LevelUpData _instance;
private final Map<Integer, L2LvlupData> _lvltable;
public static LevelUpData getInstance()
{
if (_instance == null)
{
_instance = new LevelUpData();
}
return _instance;
}
private LevelUpData()
{
_lvltable = new FastMap<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(SELECT_ALL);
ResultSet rset = statement.executeQuery())
{
L2LvlupData lvlDat;
while (rset.next())
{
lvlDat = new L2LvlupData();
lvlDat.set_classid(rset.getInt(CLASS_ID));
lvlDat.set_classLvl(rset.getInt(CLASS_LVL));
lvlDat.set_classHpBase(rset.getFloat(HP_BASE));
lvlDat.set_classHpAdd(rset.getFloat(HP_ADD));
lvlDat.set_classHpModifier(rset.getFloat(HP_MOD));
lvlDat.set_classCpBase(rset.getFloat(CP_BASE));
lvlDat.set_classCpAdd(rset.getFloat(CP_ADD));
lvlDat.set_classCpModifier(rset.getFloat(CP_MOD));
lvlDat.set_classMpBase(rset.getFloat(MP_BASE));
lvlDat.set_classMpAdd(rset.getFloat(MP_ADD));
lvlDat.set_classMpModifier(rset.getFloat(MP_MOD));
_lvltable.put(new Integer(lvlDat.get_classid()), lvlDat);
}
_log.config("LevelUpData: Loaded " + _lvltable.size() + " Character Level Up Templates.");
}
catch (final Exception e)
{
_log.warning("error while creating Lvl up data table " + e);
}
}
/**
* @param classId
* @return
*/
public L2LvlupData getTemplate(int classId)
{
return _lvltable.get(classId);
}
public L2LvlupData getTemplate(ClassId classId)
{
return _lvltable.get(classId.getId());
}
}

View File

@@ -0,0 +1,352 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.instancemanager.ArenaManager;
import com.l2jmobius.gameserver.instancemanager.CastleManager;
import com.l2jmobius.gameserver.instancemanager.ClanHallManager;
import com.l2jmobius.gameserver.instancemanager.SiegeManager;
import com.l2jmobius.gameserver.instancemanager.TownManager;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.entity.ClanHall;
import com.l2jmobius.gameserver.model.entity.Siege;
import com.l2jmobius.gameserver.model.zone.type.L2ArenaZone;
import com.l2jmobius.gameserver.model.zone.type.L2ClanHallZone;
/**
* This class ...
*/
public class MapRegionTable
{
private static Logger _log = Logger.getLogger(MapRegionTable.class.getName());
private static MapRegionTable _instance;
private final int[][] _regions = new int[19][21];
public static enum TeleportWhereType
{
Castle,
ClanHall,
SiegeFlag,
Town
}
public static MapRegionTable getInstance()
{
if (_instance == null)
{
_instance = new MapRegionTable();
}
return _instance;
}
private MapRegionTable()
{
int count2 = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT region, sec0, sec1, sec2, sec3, sec4, sec5, sec6, sec7, sec8, sec9, sec10 FROM mapregion");
ResultSet rset = statement.executeQuery())
{
int region;
while (rset.next())
{
region = rset.getInt(1);
for (int j = 0; j < 11; j++)
{
_regions[j][region] = rset.getInt(j + 2);
count2++;
}
}
if (Config.DEBUG)
{
_log.fine(count2 + " mapregion loaded");
}
}
catch (final Exception e)
{
_log.warning("error while creating map region data: " + e);
}
}
public final int getMapRegion(int posX, int posY)
{
return _regions[getMapRegionX(posX)][getMapRegionY(posY)];
}
public final int getMapRegionX(int posX)
{
return (posX >> 15) + 4;// + centerTileX;
}
public final int getMapRegionY(int posY)
{
return (posY >> 15) + 10;// + centerTileX;
}
public int getAreaCastle(L2Character activeChar)
{
final int area = getClosestTownNumber(activeChar);
int castle;
switch (area)
{
case 0:
castle = 1;
break;
case 1:
castle = 4;
break;
case 2:
castle = 4;
break;
case 5:
castle = 1;
break;
case 6:
castle = 1;
break;
case 7:
castle = 2;
break;
case 8:
castle = 3;
break;
case 9:
castle = 4;
break;
case 10:
castle = 5;
break;
case 11:
castle = 5;
break;
case 12:
castle = 3;
break;
case 13:
castle = 6;
break;
case 15:
castle = 7;
break;
case 16:
castle = 2;
break;
default:
castle = 5;
break;
}
return castle;
}
public int getClosestTownNumber(L2Character activeChar)
{
return getMapRegion(activeChar.getX(), activeChar.getY());
}
public String getClosestTownName(L2Character activeChar)
{
final int nearestTownId = getMapRegion(activeChar.getX(), activeChar.getY());
String nearestTown;
switch (nearestTownId)
{
case 0:
nearestTown = "Talking Island Village";
break;
case 1:
nearestTown = "Elven Village";
break;
case 2:
nearestTown = "Dark Elven Village";
break;
case 3:
nearestTown = "Orc Village";
break;
case 4:
nearestTown = "Dwarven Village";
break;
case 5:
nearestTown = "Gludio Castle Town";
break;
case 6:
nearestTown = "Gludin Village";
break;
case 7:
nearestTown = "Dion Castle Town";
break;
case 8:
nearestTown = "Giran Castle Town";
break;
case 9:
nearestTown = "Oren Castle Town";
break;
case 10:
nearestTown = "Aden Castle Town";
break;
case 11:
nearestTown = "Hunters Village";
break;
case 12:
nearestTown = "Giran Harbor";
break;
case 13:
nearestTown = "Innadril Castle Town";
break;
case 14:
nearestTown = "Rune Castle Town";
break;
case 15:
nearestTown = "Goddard Castle Town";
break;
case 16:
nearestTown = "Floran Village";
break;
default:
nearestTown = "Aden Castle Town";
break;
}
return nearestTown;
}
public Location getTeleToLocation(L2Character activeChar, TeleportWhereType teleportWhere)
{
// int[] coord;
if (activeChar instanceof L2PcInstance)
{
final L2PcInstance player = ((L2PcInstance) activeChar);
// If in Monster Derby Track
if (player.isInsideZone(L2Character.ZONE_MONSTERTRACK))
{
return new Location(12661, 181687, -3560);
}
Castle castle = null;
ClanHall clanhall = null;
if (player.getClan() != null)
{
// If teleport to clan hall
if (teleportWhere == TeleportWhereType.ClanHall)
{
clanhall = ClanHallManager.getInstance().getClanHallByOwner(player.getClan());
if (clanhall != null)
{
final L2ClanHallZone zone = clanhall.getZone();
if (zone != null)
{
return zone.getSpawnLoc();
}
}
}
if (teleportWhere == TeleportWhereType.Castle)
{
castle = CastleManager.getInstance().getCastleByOwner(player.getClan());
if (castle != null)
{
return castle.getZone().getSpawnLoc();
}
castle = CastleManager.getInstance().getCastle(player);
if ((castle != null) && (castle.getCastleId() > 0))
{
// If teleport to castle
if (castle.getSiege().getIsInProgress() && (castle.getSiege().getDefenderClan(player.getClan()) != null))
{
return castle.getZone().getSpawnLoc();
}
}
}
if (teleportWhere == TeleportWhereType.SiegeFlag)
{
final Siege siege = SiegeManager.getInstance().getSiege(player);
if (siege != null)
{
// Check if player's clan is attacker
final List<L2NpcInstance> flags = siege.getFlag(player.getClan());
if ((flags != null) && !flags.isEmpty())
{
// Spawn to flag - Need more work to get player to the nearest flag
final L2NpcInstance flag = flags.get(0);
return new Location(flag.getX(), flag.getY(), flag.getZ());
}
}
}
}
// Karma player land out of city
if (player.getKarma() > 0)
{
try
{
return TownManager.getInstance().getClosestTown(activeChar).getChaoticSpawnLoc();
}
catch (final Exception e)
{
return new Location(17817, 170079, -3530);
}
}
// Checking if in arena
final L2ArenaZone arena = ArenaManager.getInstance().getArena(player);
if (arena != null)
{
return arena.getSpawnLoc();
}
}
// Get the nearest town
try
{
return TownManager.getInstance().getClosestTown(activeChar).getSpawnLoc();
}
catch (final NullPointerException e)
{
// port to the Talking Island if no closest town found
return new Location(-84176, 243382, -3126);
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import com.l2jmobius.gameserver.model.L2Skill;
/**
* @author -Nemesiss-
*/
public class NobleSkillTable
{
private static NobleSkillTable _instance;
private static L2Skill[] _NobleSkills;
private NobleSkillTable()
{
_NobleSkills = new L2Skill[8];
_NobleSkills[0] = SkillTable.getInstance().getInfo(1323, 1);
_NobleSkills[1] = SkillTable.getInstance().getInfo(325, 1);
_NobleSkills[2] = SkillTable.getInstance().getInfo(326, 1);
_NobleSkills[3] = SkillTable.getInstance().getInfo(327, 1);
_NobleSkills[4] = SkillTable.getInstance().getInfo(1324, 1);
_NobleSkills[5] = SkillTable.getInstance().getInfo(1325, 1);
_NobleSkills[6] = SkillTable.getInstance().getInfo(1326, 1);
_NobleSkills[7] = SkillTable.getInstance().getInfo(1327, 1);
}
public static NobleSkillTable getInstance()
{
if (_instance == null)
{
_instance = new NobleSkillTable();
}
return _instance;
}
public L2Skill[] GetNobleSkills()
{
return _NobleSkills;
}
}

View File

@@ -0,0 +1,104 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import com.l2jmobius.L2DatabaseFactory;
import javolution.util.FastMap;
public class NpcBufferTable
{
private static NpcBufferTable _instance = null;
private final Map<Integer, Integer> _skillId = new FastMap<>();
private final Map<Integer, Integer> _skillLevels = new FastMap<>();
private final Map<Integer, Integer> _skillFeeIds = new FastMap<>();
private final Map<Integer, Integer> _skillFeeAmounts = new FastMap<>();
public void addSkill(int skillId, int skillLevel, int skillFeeId, int skillFeeAmount, int buffGroup)
{
_skillId.put(buffGroup, skillId);
_skillLevels.put(buffGroup, skillLevel);
_skillFeeIds.put(buffGroup, skillFeeId);
_skillFeeAmounts.put(buffGroup, skillFeeAmount);
}
public int[] getSkillGroupInfo(int buffGroup)
{
final Integer skillId = _skillId.get(buffGroup);
final Integer skillLevel = _skillLevels.get(buffGroup);
final Integer skillFeeId = _skillFeeIds.get(buffGroup);
final Integer skillFeeAmount = _skillFeeAmounts.get(buffGroup);
if ((skillId == null) || (skillLevel == null) || (skillFeeId == null) || (skillFeeAmount == null))
{
return null;
}
return new int[]
{
skillId,
skillLevel,
skillFeeId,
skillFeeAmount
};
}
private NpcBufferTable()
{
int skillCount = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT skill_id, skill_level, skill_fee_id, skill_fee_amount, buff_group FROM npc_buffer order by id");
ResultSet rset = statement.executeQuery())
{
while (rset.next())
{
final int skillId = rset.getInt("skill_id");
final int skillLevel = rset.getInt("skill_level");
final int skillFeeId = rset.getInt("skill_fee_id");
final int skillFeeAmount = rset.getInt("skill_fee_amount");
final int buffGroup = rset.getInt("buff_group");
addSkill(skillId, skillLevel, skillFeeId, skillFeeAmount, buffGroup);
skillCount++;
}
}
catch (final Exception e)
{
System.out.println("NpcBufferTable: Error reading npc_buffer table: " + e);
}
System.out.println("NpcBufferTable: Loaded " + skillCount + " skills.");
}
public static NpcBufferTable getInstance()
{
if (_instance == null)
{
_instance = new NpcBufferTable();
}
return _instance;
}
}

View File

@@ -0,0 +1,847 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2DropCategory;
import com.l2jmobius.gameserver.model.L2DropData;
import com.l2jmobius.gameserver.model.L2MinionData;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.skills.Stats;
import com.l2jmobius.gameserver.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.templates.StatsSet;
import javolution.util.FastList;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.8.2.6.2.9 $ $Date: 2005/04/06 16:13:25 $
*/
public class NpcTable
{
private static Logger _log = Logger.getLogger(NpcTable.class.getName());
private static NpcTable _instance;
private final Map<Integer, L2NpcTemplate> _npcs;
private boolean _initialized = false;
public static NpcTable getInstance()
{
if (_instance == null)
{
_instance = new NpcTable();
}
return _instance;
}
private NpcTable()
{
_npcs = new FastMap<>();
restoreNpcData();
}
private void restoreNpcData()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"id",
"idTemplate",
"name",
"serverSideName",
"title",
"serverSideTitle",
"class",
"collision_radius",
"collision_height",
"level",
"sex",
"type",
"attackrange",
"hp",
"mp",
"hpreg",
"mpreg",
"str",
"con",
"dex",
"int",
"wit",
"men",
"exp",
"sp",
"patk",
"pdef",
"matk",
"mdef",
"atkspd",
"aggro",
"matkspd",
"rhand",
"lhand",
"armor",
"walkspd",
"runspd",
"faction_id",
"faction_range",
"isUndead",
"absorb_level",
"ss",
"bss",
"ss_rate",
"AI"
}) + " FROM npc");
ResultSet npcdata = statement.executeQuery())
{
fillNpcTable(npcdata, false);
}
catch (final Exception e)
{
_log.severe("NPCTable: Error creating NPC table: " + e);
}
if (Config.CUSTOM_NPC_TABLE)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"id",
"idTemplate",
"name",
"serverSideName",
"title",
"serverSideTitle",
"class",
"collision_radius",
"collision_height",
"level",
"sex",
"type",
"attackrange",
"hp",
"mp",
"hpreg",
"mpreg",
"str",
"con",
"dex",
"int",
"wit",
"men",
"exp",
"sp",
"patk",
"pdef",
"matk",
"mdef",
"atkspd",
"aggro",
"matkspd",
"rhand",
"lhand",
"armor",
"walkspd",
"runspd",
"faction_id",
"faction_range",
"isUndead",
"absorb_level",
"ss",
"bss",
"ss_rate",
"AI"
}) + " FROM custom_npc");
ResultSet npcdata = statement.executeQuery())
{
fillNpcTable(npcdata, true);
}
catch (final Exception e)
{
_log.severe("NPCTable: Error creating Custom NPC table: " + e);
}
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT npcid, skillid, level FROM npcskills");
ResultSet npcskills = statement.executeQuery())
{
L2NpcTemplate npcDat = null;
L2Skill npcSkill = null;
while (npcskills.next())
{
final int mobId = npcskills.getInt("npcid");
npcDat = _npcs.get(mobId);
if (npcDat == null)
{
continue;
}
final int skillId = npcskills.getInt("skillid");
final int level = npcskills.getInt("level");
if (npcDat.race == 0)
{
if ((skillId >= 4290) && (skillId <= 4302))
{
npcDat.setRace(skillId);
continue;
}
}
npcSkill = SkillTable.getInstance().getInfo(skillId, level);
if (npcSkill == null)
{
continue;
}
npcDat.addSkill(npcSkill);
}
}
catch (final Exception e)
{
_log.severe("NPCTable: Error reading NPC skills table: " + e);
}
if (Config.CUSTOM_NPC_SKILLS_TABLE)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT npcid, skillid, level FROM custom_npcskills");
ResultSet npcskills = statement.executeQuery())
{
L2NpcTemplate npcDat = null;
L2Skill npcSkill = null;
while (npcskills.next())
{
final int mobId = npcskills.getInt("npcid");
npcDat = _npcs.get(mobId);
if (npcDat == null)
{
continue;
}
final int skillId = npcskills.getInt("skillid");
final int level = npcskills.getInt("level");
if (npcDat.race == 0)
{
if ((skillId >= 4290) && (skillId <= 4302))
{
npcDat.setRace(skillId);
continue;
}
}
npcSkill = SkillTable.getInstance().getInfo(skillId, level);
if (npcSkill == null)
{
continue;
}
npcDat.addSkill(npcSkill);
}
}
catch (final Exception e)
{
_log.severe("NPCTable: Error reading Custom NPC skills table: " + e);
}
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement2 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"mobId",
"itemId",
"min",
"max",
"category",
"chance"
}) + " FROM droplist ORDER BY mobId, chance DESC");
ResultSet dropData = statement2.executeQuery())
{
L2DropData dropDat = null;
L2NpcTemplate npcDat = null;
while (dropData.next())
{
final int mobId = dropData.getInt("mobId");
npcDat = _npcs.get(mobId);
if (npcDat == null)
{
_log.severe("NPCTable: No npc correlating with id : " + mobId);
continue;
}
dropDat = new L2DropData();
dropDat.setItemId(dropData.getInt("itemId"));
dropDat.setMinDrop(dropData.getInt("min"));
dropDat.setMaxDrop(dropData.getInt("max"));
dropDat.setChance(dropData.getInt("chance"));
final int category = dropData.getInt("category");
npcDat.addDropData(dropDat, category);
}
}
catch (final Exception e)
{
_log.severe("NPCTable: Error reading NPC drop data: " + e);
}
if (Config.CUSTOM_DROPLIST_TABLE)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement2 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"mobId",
"itemId",
"min",
"max",
"category",
"chance"
}) + " FROM custom_droplist ORDER BY mobId, chance DESC");
ResultSet dropData = statement2.executeQuery())
{
L2DropData dropDat = null;
L2NpcTemplate npcDat = null;
int cCount = 0;
while (dropData.next())
{
final int mobId = dropData.getInt("mobId");
npcDat = _npcs.get(mobId);
if (npcDat == null)
{
_log.severe("NPCTable: No custom npc correlating with id : " + mobId);
continue;
}
dropDat = new L2DropData();
dropDat.setItemId(dropData.getInt("itemId"));
dropDat.setMinDrop(dropData.getInt("min"));
dropDat.setMaxDrop(dropData.getInt("max"));
dropDat.setChance(dropData.getInt("chance"));
final int category = dropData.getInt("category");
npcDat.addDropData(dropDat, category);
cCount++;
}
_log.info("CustomDropList : Added " + cCount + " drops to custom droplist");
}
catch (final Exception e)
{
_log.severe("NPCTable: Error reading Custom NPC drop data: " + e);
}
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement3 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"npc_id",
"class_id"
}) + " FROM skill_learn");
ResultSet learndata = statement3.executeQuery())
{
while (learndata.next())
{
final int npcId = learndata.getInt("npc_id");
final int classId = learndata.getInt("class_id");
final L2NpcTemplate npc = getTemplate(npcId);
if (npc == null)
{
_log.warning("NPCTable: Error getting NPC template ID " + npcId + " while trying to load skill trainer data.");
continue;
}
npc.addTeachInfo(ClassId.values()[classId]);
}
}
catch (final Exception e)
{
_log.severe("NPCTable: Error reading NPC trainer data: " + e);
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement4 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"boss_id",
"minion_id",
"amount_min",
"amount_max"
}) + " FROM minions");
ResultSet minionData = statement4.executeQuery())
{
L2MinionData minionDat = null;
L2NpcTemplate npcDat = null;
int cnt = 0;
while (minionData.next())
{
final int raidId = minionData.getInt("boss_id");
npcDat = _npcs.get(raidId);
minionDat = new L2MinionData();
minionDat.setMinionId(minionData.getInt("minion_id"));
minionDat.setAmountMin(minionData.getInt("amount_min"));
minionDat.setAmountMax(minionData.getInt("amount_max"));
npcDat.addRaidData(minionDat);
cnt++;
}
_log.config("NpcTable: Loaded " + cnt + " Minions.");
}
catch (final Exception e)
{
_log.severe("Error loading minion data: " + e);
}
_initialized = true;
}
private void fillNpcTable(ResultSet NpcData, boolean customData) throws Exception
{
int count = 0;
while (NpcData.next())
{
final StatsSet npcDat = new StatsSet();
final int id = NpcData.getInt("id");
if (Config.ASSERT)
{
assert id < 1000000;
}
npcDat.set("npcId", id);
npcDat.set("idTemplate", NpcData.getInt("idTemplate"));
final int level = NpcData.getInt("level");
npcDat.set("level", level);
npcDat.set("jClass", NpcData.getString("class"));
npcDat.set("baseShldDef", 0);
npcDat.set("baseShldRate", 0);
npcDat.set("baseCritRate", 38);
npcDat.set("name", NpcData.getString("name"));
npcDat.set("serverSideName", NpcData.getBoolean("serverSideName"));
// npcDat.set("name", "");
npcDat.set("title", NpcData.getString("title"));
npcDat.set("serverSideTitle", NpcData.getBoolean("serverSideTitle"));
npcDat.set("collision_radius", NpcData.getDouble("collision_radius"));
npcDat.set("collision_height", NpcData.getDouble("collision_height"));
npcDat.set("sex", NpcData.getString("sex"));
npcDat.set("type", NpcData.getString("type"));
npcDat.set("baseAtkRange", NpcData.getInt("attackrange"));
npcDat.set("rewardExp", NpcData.getInt("exp"));
npcDat.set("rewardSp", NpcData.getInt("sp"));
npcDat.set("basePAtkSpd", NpcData.getInt("atkspd"));
npcDat.set("baseMAtkSpd", NpcData.getInt("matkspd"));
npcDat.set("aggroRange", NpcData.getInt("aggro"));
npcDat.set("rhand", NpcData.getInt("rhand"));
npcDat.set("lhand", NpcData.getInt("lhand"));
npcDat.set("armor", NpcData.getInt("armor"));
npcDat.set("baseWalkSpd", NpcData.getInt("walkspd"));
npcDat.set("baseRunSpd", NpcData.getInt("runspd"));
// constants, until we have stats in DB
npcDat.set("baseSTR", NpcData.getInt("str"));
npcDat.set("baseCON", NpcData.getInt("con"));
npcDat.set("baseDEX", NpcData.getInt("dex"));
npcDat.set("baseINT", NpcData.getInt("int"));
npcDat.set("baseWIT", NpcData.getInt("wit"));
npcDat.set("baseMEN", NpcData.getInt("men"));
npcDat.set("baseHpMax", NpcData.getInt("hp"));
npcDat.set("baseCpMax", 0);
npcDat.set("baseMpMax", NpcData.getInt("mp"));
npcDat.set("baseHpReg", NpcData.getFloat("hpreg") > 0 ? NpcData.getFloat("hpreg") : 1.5 + ((level - 1) / 10));
npcDat.set("baseMpReg", NpcData.getFloat("mpreg") > 0 ? NpcData.getFloat("mpreg") : 0.9 + (0.3 * ((level - 1) / 10)));
npcDat.set("basePAtk", NpcData.getInt("patk"));
npcDat.set("basePDef", NpcData.getInt("pdef"));
npcDat.set("baseMAtk", NpcData.getInt("matk"));
npcDat.set("baseMDef", NpcData.getInt("mdef"));
npcDat.set("factionId", NpcData.getString("faction_id"));
npcDat.set("factionRange", NpcData.getInt("faction_range"));
npcDat.set("isUndead", NpcData.getString("isUndead"));
npcDat.set("absorb_level", NpcData.getString("absorb_level"));
npcDat.set("ss", NpcData.getInt("ss"));
npcDat.set("bss", NpcData.getInt("bss"));
npcDat.set("ssRate", NpcData.getInt("ss_rate"));
npcDat.set("AI", NpcData.getString("AI"));
final L2NpcTemplate template = new L2NpcTemplate(npcDat);
template.addVulnerability(Stats.BOW_WPN_VULN, 1);
template.addVulnerability(Stats.BLUNT_WPN_VULN, 1);
template.addVulnerability(Stats.DAGGER_WPN_VULN, 1);
final L2NpcTemplate oldTemplate = getTemplate(id);
if (oldTemplate != null)
{
// add quest events to the new template
if (oldTemplate.questEvents != null)
{
template.questEvents = oldTemplate.questEvents;
}
}
_npcs.put(id, template);
count++;
}
if (count > 0)
{
if (!customData)
{
_log.config("NpcTable: (Re)Loaded " + count + " NPC template(s).");
}
else
{
_log.config("NpcTable: (Re)Loaded " + count + " custom NPC template(s).");
}
}
}
public void reloadNpc(int id)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
// save a copy of the old data
final L2NpcTemplate old = getTemplate(id);
final Map<Integer, L2Skill> skills = new FastMap<>();
if (old.getSkills() != null)
{
skills.putAll(old.getSkills());
}
final FastList<L2DropCategory> categories = new FastList<>();
if (old.getDropData() != null)
{
categories.addAll(old.getDropData());
}
ClassId[] classIds = null;
if (old.getTeachInfo() != null)
{
classIds = old.getTeachInfo().clone();
}
final List<L2MinionData> minions = new FastList<>();
if (old.getMinionData() != null)
{
minions.addAll(old.getMinionData());
}
// reload the NPC base data
try (PreparedStatement st = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"id",
"idTemplate",
"name",
"serverSideName",
"title",
"serverSideTitle",
"class",
"collision_radius",
"collision_height",
"level",
"sex",
"type",
"attackrange",
"hp",
"mp",
"hpreg",
"mpreg",
"str",
"con",
"dex",
"int",
"wit",
"men",
"exp",
"sp",
"patk",
"pdef",
"matk",
"mdef",
"atkspd",
"aggro",
"matkspd",
"rhand",
"lhand",
"armor",
"walkspd",
"runspd",
"faction_id",
"faction_range",
"isUndead",
"absorb_level",
"ss",
"bss",
"ss_rate",
"AI"
}) + " FROM npc WHERE id=?"))
{
st.setInt(1, id);
try (ResultSet rs = st.executeQuery())
{
fillNpcTable(rs, false);
}
}
if (Config.CUSTOM_NPC_TABLE) // reload certain NPCs
{
try (PreparedStatement st = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
{
"id",
"idTemplate",
"name",
"serverSideName",
"title",
"serverSideTitle",
"class",
"collision_radius",
"collision_height",
"level",
"sex",
"type",
"attackrange",
"hp",
"mp",
"hpreg",
"mpreg",
"str",
"con",
"dex",
"int",
"wit",
"men",
"exp",
"sp",
"patk",
"pdef",
"matk",
"mdef",
"atkspd",
"aggro",
"matkspd",
"rhand",
"lhand",
"armor",
"walkspd",
"runspd",
"faction_id",
"faction_range",
"isUndead",
"absorb_level",
"ss",
"bss",
"ss_rate",
"AI"
}) + " FROM custom_npc WHERE id=?"))
{
st.setInt(1, id);
try (ResultSet rs = st.executeQuery())
{
fillNpcTable(rs, true);
}
}
}
// restore additional data from saved copy
final L2NpcTemplate created = getTemplate(id);
// set race
created.setRace(old.race);
for (final L2Skill skill : skills.values())
{
created.addSkill(skill);
}
if (classIds != null)
{
for (final ClassId classId : classIds)
{
created.addTeachInfo(classId);
}
}
for (final L2MinionData minion : minions)
{
created.addRaidData(minion);
}
}
catch (final Exception e)
{
_log.warning("NPCTable: Could not reload data for NPC " + id + ": " + e);
}
}
// just wrapper
public void reloadAllNpc()
{
restoreNpcData();
}
public void saveNpc(StatsSet npc)
{
String query = "";
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
final Map<String, Object> set = npc.getSet();
String name = "";
String values = "";
for (final Object obj : set.keySet())
{
name = (String) obj;
if (name.equalsIgnoreCase("npcId"))
{
continue;
}
if (!values.isEmpty())
{
values += ", ";
}
values += name + " = '" + set.get(name) + "'";
}
int updated = 0;
if (Config.CUSTOM_NPC_TABLE)
{
query = "UPDATE custom_npc SET " + values + " WHERE id = ?";
try (PreparedStatement statement = con.prepareStatement(query))
{
statement.setInt(1, npc.getInteger("npcId"));
updated = statement.executeUpdate();
}
}
if (updated == 0)
{
query = "UPDATE npc SET " + values + " WHERE id = ?";
try (PreparedStatement statement = con.prepareStatement(query))
{
statement.setInt(1, npc.getInteger("npcId"));
statement.executeUpdate();
}
}
}
catch (final Exception e)
{
_log.warning("NPCTable: Could not store new NPC data in database: " + e);
}
}
public boolean isInitialized()
{
return _initialized;
}
public void replaceTemplate(L2NpcTemplate npc)
{
_npcs.put(npc.npcId, npc);
}
public L2NpcTemplate getTemplate(int id)
{
return _npcs.get(id);
}
public L2NpcTemplate getTemplateByName(String name)
{
for (final L2NpcTemplate npcTemplate : _npcs.values())
{
if (npcTemplate.name.equalsIgnoreCase(name))
{
return npcTemplate;
}
}
return null;
}
public L2NpcTemplate[] getAllOfLevel(int lvl)
{
final List<L2NpcTemplate> list = new FastList<>();
for (final L2NpcTemplate t : _npcs.values())
{
if (t.level == lvl)
{
list.add(t);
}
}
return list.toArray(new L2NpcTemplate[list.size()]);
}
public L2NpcTemplate[] getAllMonstersOfLevel(int lvl)
{
final List<L2NpcTemplate> list = new FastList<>();
for (final L2NpcTemplate t : _npcs.values())
{
if ((t.level == lvl) && "L2Monster".equals(t.type))
{
list.add(t);
}
}
return list.toArray(new L2NpcTemplate[list.size()]);
}
public L2NpcTemplate[] getAllNpcStartingWith(String letter)
{
final List<L2NpcTemplate> list = new FastList<>();
for (final L2NpcTemplate t : _npcs.values())
{
if (t.name.startsWith(letter) && "L2Npc".equals(t.type))
{
list.add(t);
}
}
return list.toArray(new L2NpcTemplate[list.size()]);
}
}

View File

@@ -0,0 +1,104 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2NpcWalkerNode;
import javolution.util.FastList;
/**
* Main Table to Load Npc Walkers Routes and Chat SQL Table.<br>
* @author Rayan RPG for L2Emu Project
* @since 927
*/
public class NpcWalkerRoutesTable
{
private static Logger _log = Logger.getLogger(NpcWalkerRoutesTable.class.getName());
private static NpcWalkerRoutesTable _instance;
private final FastList<L2NpcWalkerNode> _routes = new FastList<>();
public static NpcWalkerRoutesTable getInstance()
{
if (_instance == null)
{
_instance = new NpcWalkerRoutesTable();
_log.info("Initializing Walker Routes Table.");
}
return _instance;
}
private NpcWalkerRoutesTable()
{
load();
}
public void load()
{
_routes.clear();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT route_id, npc_id, move_point, chatText, move_x, move_y, move_z, delay, running FROM walker_routes ORDER By move_point ASC");
ResultSet rset = statement.executeQuery())
{
L2NpcWalkerNode route;
while (rset.next())
{
route = new L2NpcWalkerNode();
route.setRouteId(rset.getInt("route_id"));
route.setNpcId(rset.getInt("npc_id"));
route.setMovePoint(rset.getString("move_point"));
route.setChatText(rset.getString("chatText"));
route.setMoveX(rset.getInt("move_x"));
route.setMoveY(rset.getInt("move_y"));
route.setMoveZ(rset.getInt("move_z"));
route.setDelay(rset.getInt("delay"));
route.setRunning(rset.getBoolean("running"));
_routes.add(route);
}
_log.info("WalkerRoutesTable: Loaded " + _routes.size() + " Npc Walker Routes.");
}
catch (final Exception e)
{
_log.warning("WalkerRoutesTable: Error while loading Npc Walkers Routes: " + e.getMessage());
}
}
public FastList<L2NpcWalkerNode> getRouteForNpc(int id)
{
final FastList<L2NpcWalkerNode> _return = new FastList<>();
for (FastList.Node<L2NpcWalkerNode> n = _routes.head(), end = _routes.tail(); (n = n.getNext()) != end;)
{
if (n.getValue().getNpcId() == id)
{
_return.add(n.getValue());
}
}
return _return;
}
}

View File

@@ -0,0 +1,265 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
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 com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.LoginServerThread;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2ManufactureList;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.TradeList.TradeItem;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.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 (`char_id`,`time`,`type`,`title`) VALUES (?,?,?,?)";
private static final String SAVE_ITEMS = "INSERT INTO character_offline_trade_items (`char_id`,`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 char_id = ?";
public static void storeOffliners()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement stm1 = con.prepareStatement(CLEAR_OFFLINE_TABLE);
PreparedStatement stm2 = con.prepareStatement(CLEAR_OFFLINE_TABLE_ITEMS);
PreparedStatement stm3 = con.prepareStatement(SAVE_OFFLINE_STATUS);
PreparedStatement stm_items = con.prepareStatement(SAVE_ITEMS))
{
stm1.execute();
stm2.execute();
con.setAutoCommit(false); // avoid halfway done
for (final L2PcInstance pc : L2World.getInstance().getAllPlayers())
{
try
{
if (pc.inOfflineMode())
{
stm3.setInt(1, pc.getObjectId()); // Char Id
stm3.setLong(2, pc.getOfflineStartTime());
stm3.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 (final 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 (final 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 (final L2ManufactureItem i : pc.getCreateList().getList())
{
stm_items.setInt(1, pc.getObjectId());
stm_items.setInt(2, i.getRecipeId());
stm_items.setInt(3, 0);
stm_items.setInt(4, i.getCost());
stm_items.executeUpdate();
stm_items.clearParameters();
}
}
stm3.setString(4, title);
stm3.executeUpdate();
stm3.clearParameters();
con.commit(); // flush
}
}
catch (final Exception e)
{
_log.log(Level.WARNING, "OfflineTradersTable[storeTradeItems()]: Error while saving offline trader: " + pc.getObjectId() + " " + e, e);
}
}
_log.info("Offline traders stored.");
}
catch (final Exception e)
{
_log.log(Level.WARNING, "OfflineTradersTable[storeTradeItems()]: Error while saving offline traders: " + e, e);
}
}
public static void restoreOfflineTraders()
{
_log.info("Loading offline traders...");
int nTraders = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement stm = con.prepareStatement(LOAD_OFFLINE_STATUS);
ResultSet rs = stm.executeQuery())
{
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;
}
}
final int type = rs.getInt("type");
if (type == L2PcInstance.STORE_PRIVATE_NONE)
{
continue;
}
L2PcInstance player = null;
try
{
final L2GameClient client = new L2GameClient(null);
client.setDetached(true);
player = L2PcInstance.load(rs.getInt("char_id"));
client.setActiveChar(player);
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);
try (PreparedStatement stm_items = con.prepareStatement(LOAD_OFFLINE_ITEMS))
{
stm_items.setInt(1, player.getObjectId());
try (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:
final 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;
}
}
}
player.sitDown();
player.setInOfflineMode();
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 (final Exception e)
{
_log.log(Level.WARNING, "OfflineTradersTable[loadOffliners()]: Error loading trader: " + player, e);
if (player != null)
{
player.logout();
}
}
}
_log.info("Loaded: " + nTraders + " offline trader(s)");
try (Statement stm1 = con.createStatement())
{
stm1.execute(CLEAR_OFFLINE_TABLE);
stm1.execute(CLEAR_OFFLINE_TABLE_ITEMS);
}
}
catch (final Exception e)
{
_log.log(Level.WARNING, "OfflineTradersTable[loadOffliners()]: Error while loading offline traders: ", e);
}
}
}

View File

@@ -0,0 +1,120 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2PetDataTable;
public class PetNameTable
{
private static Logger _log = Logger.getLogger(PetNameTable.class.getName());
private static PetNameTable _instance;
public static PetNameTable getInstance()
{
if (_instance == null)
{
_instance = new PetNameTable();
}
return _instance;
}
public boolean doesPetNameExist(String name, int petNpcId)
{
boolean result = true;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT name FROM pets p, items i WHERE p.item_obj_id = i.object_id AND name=? AND i.item_id IN (?)"))
{
statement.setString(1, name);
String cond = "";
for (final int it : L2PetDataTable.getPetItemsAsNpc(petNpcId))
{
if (!cond.isEmpty())
{
cond += ", ";
}
cond += it;
}
statement.setString(2, cond);
try (ResultSet rset = statement.executeQuery())
{
result = rset.next();
}
}
catch (final SQLException e)
{
_log.warning("could not check existing petname:" + e.getMessage());
}
return result;
}
public boolean isValidPetName(String name)
{
boolean result = true;
if (!isAlphaNumeric(name))
{
return result;
}
Pattern pattern;
try
{
pattern = Pattern.compile(Config.PET_NAME_TEMPLATE);
}
catch (final PatternSyntaxException e) // case of illegal pattern
{
_log.warning("ERROR : Pet name pattern of config is wrong!");
pattern = Pattern.compile(".*");
}
final Matcher regexp = pattern.matcher(name);
if (!regexp.matches())
{
result = false;
}
return result;
}
private boolean isAlphaNumeric(String text)
{
boolean result = true;
final char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; i++)
{
if (!Character.isLetterOrDigit(chars[i]))
{
result = false;
break;
}
}
return result;
}
}

View File

@@ -0,0 +1,81 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2Skill;
import javolution.util.FastMap;
public class SkillSpellbookTable
{
private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
private static SkillSpellbookTable _instance;
private static Map<Integer, Integer> _skillSpellbooks;
public static SkillSpellbookTable getInstance()
{
if (_instance == null)
{
_instance = new SkillSpellbookTable();
}
return _instance;
}
private SkillSpellbookTable()
{
_skillSpellbooks = new FastMap<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT skill_id, item_id FROM skill_spellbooks");
ResultSet spbooks = statement.executeQuery())
{
while (spbooks.next())
{
_skillSpellbooks.put(spbooks.getInt("skill_id"), spbooks.getInt("item_id"));
}
_log.config("SkillSpellbookTable: Loaded " + _skillSpellbooks.size() + " Spellbooks.");
}
catch (final Exception e)
{
_log.warning("Error while loading spellbook data: " + e);
}
}
public int getBookForSkill(int skillId)
{
if (!_skillSpellbooks.containsKey(skillId))
{
return -1;
}
return _skillSpellbooks.get(skillId);
}
public int getBookForSkill(L2Skill skill)
{
return getBookForSkill(skill.getId());
}
}

View File

@@ -0,0 +1,143 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.util.HashMap;
import java.util.Map;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.skills.SkillsEngine;
import com.l2jmobius.gameserver.templates.L2WeaponType;
import gnu.trove.map.hash.TIntIntHashMap;
/**
*
*/
public class SkillTable
{
private static SkillTable _instance;
private final Map<Integer, L2Skill> _skills;
private final TIntIntHashMap _skillMaxLevel;
public static SkillTable getInstance()
{
if (_instance == null)
{
_instance = new SkillTable();
}
return _instance;
}
private SkillTable()
{
_skills = new HashMap<>();
_skillMaxLevel = new TIntIntHashMap();
reload();
}
public void reload()
{
_skills.clear();
SkillsEngine.getInstance().loadAllSkills(_skills);
_skillMaxLevel.clear();
for (final L2Skill skill : _skills.values())
{
final int skillLvl = skill.getLevel();
if (skillLvl > 99)
{
continue;
}
final int skillId = skill.getId();
final int maxLvl = _skillMaxLevel.get(skillId);
if (skillLvl > maxLvl)
{
_skillMaxLevel.put(skillId, skillLvl);
}
}
}
/**
* Provides the skill hash
* @param skill The L2Skill to be hashed
* @return getSkillHashCode(skill.getId(), skill.getLevel())
*/
public static int getSkillHashCode(L2Skill skill)
{
return getSkillHashCode(skill.getId(), skill.getLevel());
}
/**
* Centralized method for easier change of the hashing sys
* @param skillId The Skill Id
* @param skillLevel The Skill Level
* @return The Skill hash number
*/
public static int getSkillHashCode(int skillId, int skillLevel)
{
return (skillId * 256) + skillLevel;
}
public final L2Skill getInfo(final int skillId, final int level)
{
return _skills.get(getSkillHashCode(skillId, level));
}
public final int getMaxLevel(final int skillId)
{
return _skillMaxLevel.get(skillId);
}
private static final L2WeaponType[] weaponDbMasks =
{
L2WeaponType.ETC,
L2WeaponType.BOW,
L2WeaponType.POLE,
L2WeaponType.DUALFIST,
L2WeaponType.DUAL,
L2WeaponType.BLUNT,
L2WeaponType.SWORD,
L2WeaponType.DAGGER,
L2WeaponType.BIGSWORD,
L2WeaponType.ROD,
L2WeaponType.BIGBLUNT
};
public int calcWeaponsAllowed(int mask)
{
if (mask == 0)
{
return 0;
}
int weaponsAllowed = 0;
for (int i = 0; i < weaponDbMasks.length; i++)
{
if ((mask & (1 << i)) != 0)
{
weaponsAllowed |= weaponDbMasks[i].mask();
}
}
return weaponsAllowed;
}
}

View File

@@ -0,0 +1,761 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2EnchantSkillLearn;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.L2SkillLearn;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.base.ClassId;
import gnu.trove.map.hash.TIntObjectHashMap;
import javolution.util.FastList;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.13.2.2.2.8 $ $Date: 2005/04/06 16:13:25 $
*/
public class SkillTreeTable
{
private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
private static SkillTreeTable _instance;
private Map<ClassId, Map<Integer, L2SkillLearn>> _skillTrees;
private List<L2SkillLearn> _fishingSkillTrees; // all common skills (teached by Fisherman)
private List<L2SkillLearn> _expandDwarfCraftSkillTrees; // list of special skill for dwarf (expand dwarf craft) learned by class teacher
private Map<Integer, L2EnchantSkillLearn> _enchantSkillTrees; // enchant skill list
// checker, sorted arrays of hashcodes
private TIntObjectHashMap<int[]> _skillsByClassIdHashCodes; // occupation skills
private int[] _allSkillsHashCodes; // fishing, and special
private boolean _loading = true;
public static SkillTreeTable getInstance()
{
if (_instance == null)
{
_instance = new SkillTreeTable();
}
return _instance;
}
/**
* Return the minimum level needed to have this Expertise.<BR>
* <BR>
* @param grade The grade level searched
* @return
*/
public int getExpertiseLevel(int grade)
{
if (grade <= 0)
{
return 0;
}
// since expertise comes at same level for all classes we use paladin for now
final Map<Integer, L2SkillLearn> learnMap = getSkillTrees().get(ClassId.paladin);
final int skillHashCode = SkillTable.getSkillHashCode(239, grade);
if (learnMap.containsKey(skillHashCode))
{
return learnMap.get(skillHashCode).getMinLevel();
}
_log.severe("Expertise not found for grade " + grade);
return 0;
}
/**
* Each class receives new skill on certain levels, this methods allow the retrieval of the minimun character level of given class required to learn a given skill
* @param skillId The iD of the skill
* @param classId The classId of the character
* @param skillLvl The SkillLvl
* @return The min level
*/
public int getMinSkillLevel(int skillId, ClassId classId, int skillLvl)
{
final Map<Integer, L2SkillLearn> map = getSkillTrees().get(classId);
final int skillHashCode = SkillTable.getSkillHashCode(skillId, skillLvl);
if (map.containsKey(skillHashCode))
{
return map.get(skillHashCode).getMinLevel();
}
return 0;
}
public int getMinSkillLevel(int skillId, int skillLvl)
{
final int skillHashCode = SkillTable.getSkillHashCode(skillId, skillLvl);
// Look on all classes for this skill (takes the first one found)
for (final Map<Integer, L2SkillLearn> map : getSkillTrees().values())
{
// checks if the current class has this skill
if (map.containsKey(skillHashCode))
{
return map.get(skillHashCode).getMinLevel();
}
}
return 0;
}
private SkillTreeTable()
{
_loading = true;
int classId = 0;
int count = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM class_list ORDER BY id");
ResultSet classlist = statement.executeQuery())
{
Map<Integer, L2SkillLearn> map;
int parentClassId;
L2SkillLearn skillLearn;
while (classlist.next())
{
map = new FastMap<>();
parentClassId = classlist.getInt("parent_id");
classId = classlist.getInt("id");
if (parentClassId != -1)
{
final Map<Integer, L2SkillLearn> parentMap = getSkillTrees().get(ClassId.values()[parentClassId]);
map.putAll(parentMap);
}
try (PreparedStatement statement2 = con.prepareStatement("SELECT class_id, skill_id, level, name, sp, min_level FROM skill_trees where class_id=? ORDER BY skill_id, level"))
{
statement2.setInt(1, classId);
try (ResultSet skilltree = statement2.executeQuery())
{
int prevSkillId = -1;
while (skilltree.next())
{
final int id = skilltree.getInt("skill_id");
final int lvl = skilltree.getInt("level");
final String name = skilltree.getString("name");
final int minLvl = skilltree.getInt("min_level");
final int cost = skilltree.getInt("sp");
if (prevSkillId != id)
{
prevSkillId = id;
}
skillLearn = new L2SkillLearn(id, lvl, minLvl, name, cost, 0, 0);
map.put(SkillTable.getSkillHashCode(id, lvl), skillLearn);
}
}
}
getSkillTrees().put(ClassId.values()[classId], map);
count += map.size();
_log.fine("SkillTreeTable: skill tree for class " + classId + " has " + map.size() + " skills");
}
}
catch (final Exception e)
{
_log.severe("Error while creating skill tree (Class ID " + classId + "):" + e);
}
_log.config("SkillTreeTable: Loaded " + count + " skills.");
// Skill tree for fishing skill (from Fisherman)
int count2 = 0;
int count3 = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT skill_id, level, name, sp, min_level, costid, cost, isfordwarf FROM fishing_skill_trees ORDER BY skill_id, level");
ResultSet skilltree2 = statement.executeQuery())
{
_fishingSkillTrees = new FastList<>();
_expandDwarfCraftSkillTrees = new FastList<>();
int prevSkillId = -1;
while (skilltree2.next())
{
final int id = skilltree2.getInt("skill_id");
final int lvl = skilltree2.getInt("level");
final String name = skilltree2.getString("name");
final int minLvl = skilltree2.getInt("min_level");
final int cost = skilltree2.getInt("sp");
final int costId = skilltree2.getInt("costid");
final int costCount = skilltree2.getInt("cost");
final int isDwarven = skilltree2.getInt("isfordwarf");
if (prevSkillId != id)
{
prevSkillId = id;
}
final L2SkillLearn skill = new L2SkillLearn(id, lvl, minLvl, name, cost, costId, costCount);
if (isDwarven == 0)
{
_fishingSkillTrees.add(skill);
}
else
{
_expandDwarfCraftSkillTrees.add(skill);
}
}
count2 = _fishingSkillTrees.size();
count3 = _expandDwarfCraftSkillTrees.size();
}
catch (final Exception e)
{
_log.severe("Error while creating fishing skill table: " + e);
}
int count4 = 0;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT skill_id, level, name, base_lvl, sp, min_skill_lvl, exp, success_rate76, success_rate77, success_rate78 FROM enchant_skill_trees ORDER BY skill_id, level");
ResultSet skilltree3 = statement.executeQuery())
{
_enchantSkillTrees = new FastMap<>();
int prevSkillId = -1;
while (skilltree3.next())
{
final int id = skilltree3.getInt("skill_id");
final int lvl = skilltree3.getInt("level");
final String name = skilltree3.getString("name");
final int baseLvl = skilltree3.getInt("base_lvl");
final int minSkillLvl = skilltree3.getInt("min_skill_lvl");
final int sp = skilltree3.getInt("sp");
final int exp = skilltree3.getInt("exp");
final byte rate76 = skilltree3.getByte("success_rate76");
final byte rate77 = skilltree3.getByte("success_rate77");
final byte rate78 = skilltree3.getByte("success_rate78");
if (prevSkillId != id)
{
prevSkillId = id;
}
final L2EnchantSkillLearn skill = new L2EnchantSkillLearn(id, lvl, minSkillLvl, baseLvl, name, sp, exp, rate76, rate77, rate78);
_enchantSkillTrees.put(SkillTable.getSkillHashCode(id, lvl), skill);
}
count4 = _enchantSkillTrees.size();
}
catch (final Exception e)
{
_log.severe("Error while creating enchant skill table: " + e);
}
generateCheckArrays();
_log.config("FishingSkillTreeTable: Loaded " + count2 + " general skills.");
_log.config("FishingSkillTreeTable: Loaded " + count3 + " dwarven skills.");
_log.config("EnchantSkillTreeTable: Loaded " + count4 + " enchant skills.");
_loading = false;
}
private void generateCheckArrays()
{
int i;
int[] array;
// class-specific skills
Map<Integer, L2SkillLearn> tempMap;
final TIntObjectHashMap<int[]> result = new TIntObjectHashMap<>(_skillTrees.keySet().size());
for (final ClassId cls : _skillTrees.keySet())
{
i = 0;
tempMap = _skillTrees.get(cls);
array = new int[tempMap.size()];
for (final int h : tempMap.keySet())
{
array[i++] = h;
}
Arrays.sort(array);
result.put(cls.ordinal(), array);
}
_skillsByClassIdHashCodes = result;
// skills available for all classes and races
final FastList<Integer> list = FastList.newInstance();
for (final L2SkillLearn s : _fishingSkillTrees)
{
list.add(SkillTable.getSkillHashCode(s.getId(), s.getLevel()));
}
for (final L2SkillLearn s : _expandDwarfCraftSkillTrees)
{
list.add(SkillTable.getSkillHashCode(s.getId(), s.getLevel()));
}
i = 0;
array = new int[list.size()];
for (final int s : list)
{
array[i++] = s;
}
Arrays.sort(array);
_allSkillsHashCodes = array;
FastList.recycle(list);
}
private Map<ClassId, Map<Integer, L2SkillLearn>> getSkillTrees()
{
if (_skillTrees == null)
{
_skillTrees = new FastMap<>();
}
return _skillTrees;
}
public L2SkillLearn[] getMaxAvailableSkills(L2PcInstance cha, ClassId classId)
{
final Map<Integer, L2SkillLearn> result = new FastMap<>();
final Collection<L2SkillLearn> skills = getSkillTrees().get(classId).values();
if (skills == null)
{
// the skilltree for this class is undefined, so we give an empty list
_log.warning("Skilltree for class " + classId + " is not defined !");
return new L2SkillLearn[0];
}
final L2Skill[] oldSkills = cha.getAllSkills();
for (final L2SkillLearn temp : skills)
{
if (temp.getMinLevel() <= cha.getLevel())
{
boolean knownSkill = false;
for (int j = 0; (j < oldSkills.length) && !knownSkill; j++)
{
if (oldSkills[j].getId() == temp.getId())
{
knownSkill = true;
if (oldSkills[j].getLevel() < temp.getLevel())
{
// this is the next level of a skill that we know
result.put(temp.getId(), temp);
}
}
}
if (!knownSkill)
{
// this is a new skill
result.put(temp.getId(), temp);
}
}
}
return result.values().toArray(new L2SkillLearn[result.size()]);
}
public L2SkillLearn[] getAvailableSkills(L2PcInstance cha, ClassId classId)
{
final List<L2SkillLearn> result = new FastList<>();
final Collection<L2SkillLearn> skills = getSkillTrees().get(classId).values();
if (skills == null)
{
// the skilltree for this class is undefined, so we give an empty list
_log.warning("Skilltree for class " + classId + " is not defined !");
return new L2SkillLearn[0];
}
final L2Skill[] oldSkills = cha.getAllSkills();
for (final L2SkillLearn temp : skills)
{
if (temp.getMinLevel() <= cha.getLevel())
{
boolean knownSkill = false;
for (int j = 0; (j < oldSkills.length) && !knownSkill; j++)
{
if (oldSkills[j].getId() == temp.getId())
{
knownSkill = true;
if (oldSkills[j].getLevel() == (temp.getLevel() - 1))
{
// this is the next level of a skill that we know
result.add(temp);
}
}
}
if (!knownSkill && (temp.getLevel() == 1))
{
// this is a new skill
result.add(temp);
}
}
}
return result.toArray(new L2SkillLearn[result.size()]);
}
public L2SkillLearn[] getAvailableSkills(L2PcInstance cha)
{
final List<L2SkillLearn> result = new FastList<>();
final List<L2SkillLearn> skills = new FastList<>();
skills.addAll(_fishingSkillTrees);
// if (skills == null)
// {
// // the skilltree for this class is undefined, so we give an empty list
// _log.warning("Skilltree for fishing is not defined !");
// return new L2SkillLearn[0];
// }
if (cha.hasDwarvenCraft() && (_expandDwarfCraftSkillTrees != null))
{
skills.addAll(_expandDwarfCraftSkillTrees);
}
final L2Skill[] oldSkills = cha.getAllSkills();
for (final L2SkillLearn temp : skills)
{
if (temp.getMinLevel() <= cha.getLevel())
{
boolean knownSkill = false;
for (int j = 0; (j < oldSkills.length) && !knownSkill; j++)
{
if (oldSkills[j].getId() == temp.getId())
{
knownSkill = true;
if (oldSkills[j].getLevel() == (temp.getLevel() - 1))
{
// this is the next level of a skill that we know
result.add(temp);
}
}
}
if (!knownSkill && (temp.getLevel() == 1))
{
// this is a new skill
result.add(temp);
}
}
}
return result.toArray(new L2SkillLearn[result.size()]);
}
public L2EnchantSkillLearn[] getAvailableEnchantSkills(L2PcInstance cha)
{
final List<L2EnchantSkillLearn> result = new FastList<>();
final Map<Integer, L2EnchantSkillLearn> skills = new FastMap<>();
skills.putAll(_enchantSkillTrees);
// if (skills == null)
// {
// // the skilltree for this class is undefined, so we give an empty list
// _log.warning("Skilltree for enchanting is not defined !");
// return new L2EnchantSkillLearn[0];
// }
final L2Skill[] oldSkills = cha.getAllSkills();
for (final L2EnchantSkillLearn temp : skills.values())
{
if (cha.getLevel() >= 76)
{
boolean knownSkill = false;
for (int j = 0; (j < oldSkills.length) && !knownSkill; j++)
{
if (oldSkills[j].getId() == temp.getId())
{
knownSkill = true;
if (oldSkills[j].getLevel() == temp.getMinSkillLevel())
{
// this is the next level of a skill that we know
result.add(temp);
}
}
}
}
}
return result.toArray(new L2EnchantSkillLearn[result.size()]);
}
/**
* Returns all allowed skills for a given class.
* @param classId
* @return all allowed skills for a given class.
*/
public Collection<L2SkillLearn> getAllowedSkills(ClassId classId)
{
return getSkillTrees().get(classId).values();
}
public int getMinLevelForNewSkill(L2PcInstance cha, ClassId classId)
{
int minLevel = 0;
final Collection<L2SkillLearn> skills = getSkillTrees().get(classId).values();
if (skills == null)
{
// the skilltree for this class is undefined, so we give an empty list
_log.warning("Skilltree for class " + classId + " is not defined !");
return minLevel;
}
for (final L2SkillLearn temp : skills)
{
if ((temp.getMinLevel() > cha.getLevel()) && (temp.getSpCost() != 0))
{
if ((minLevel == 0) || (temp.getMinLevel() < minLevel))
{
minLevel = temp.getMinLevel();
}
}
}
return minLevel;
}
public int getMinLevelForNewSkill(L2PcInstance cha)
{
int minLevel = 0;
final List<L2SkillLearn> skills = new FastList<>();
skills.addAll(_fishingSkillTrees);
// if (skills == null)
// {
// // the skilltree for this class is undefined, so we give an empty list
// _log.warning("SkillTree for fishing is not defined!");
// return minLevel;
// }
if (cha.hasDwarvenCraft() && (_expandDwarfCraftSkillTrees != null))
{
skills.addAll(_expandDwarfCraftSkillTrees);
}
for (final L2SkillLearn s : skills)
{
if (s.getMinLevel() > cha.getLevel())
{
if ((minLevel == 0) || (s.getMinLevel() < minLevel))
{
minLevel = s.getMinLevel();
}
}
}
return minLevel;
}
public int getSkillCost(L2PcInstance player, L2Skill skill)
{
int skillCost = 100000000;
final ClassId classId = player.getSkillLearningClassId();
final int skillHashCode = SkillTable.getSkillHashCode(skill);
if (getSkillTrees().get(classId).containsKey(skillHashCode))
{
final L2SkillLearn skillLearn = getSkillTrees().get(classId).get(skillHashCode);
if (skillLearn.getMinLevel() <= player.getLevel())
{
skillCost = skillLearn.getSpCost();
if (!player.getClassId().equalsOrChildOf(classId))
{
if (skill.getCrossLearnAdd() < 0)
{
return skillCost;
}
skillCost += skill.getCrossLearnAdd();
skillCost *= skill.getCrossLearnMul();
}
if ((classId.getRace() != player.getRace()) && !player.isSubClassActive())
{
skillCost *= skill.getCrossLearnRace();
}
if (classId.isMage() != player.getClassId().isMage())
{
skillCost *= skill.getCrossLearnProf();
}
}
}
return skillCost;
}
public int getSkillSpCost(L2PcInstance player, L2Skill skill)
{
int skillCost = 100000000;
final L2EnchantSkillLearn[] enchantSkillLearnList = getAvailableEnchantSkills(player);
for (final L2EnchantSkillLearn enchantSkillLearn : enchantSkillLearnList)
{
if (enchantSkillLearn.getId() != skill.getId())
{
continue;
}
if (enchantSkillLearn.getLevel() != skill.getLevel())
{
continue;
}
if (player.getLevel() < 76)
{
continue;
}
skillCost = enchantSkillLearn.getSpCost();
}
return skillCost;
}
public int getSkillExpCost(L2PcInstance player, L2Skill skill)
{
int skillCost = 100000000;
final L2EnchantSkillLearn[] enchantSkillLearnList = getAvailableEnchantSkills(player);
for (final L2EnchantSkillLearn enchantSkillLearn : enchantSkillLearnList)
{
if (enchantSkillLearn.getId() != skill.getId())
{
continue;
}
if (enchantSkillLearn.getLevel() != skill.getLevel())
{
continue;
}
if (player.getLevel() < 76)
{
continue;
}
skillCost = enchantSkillLearn.getExp();
}
return skillCost;
}
public byte getSkillRate(L2PcInstance player, L2Skill skill)
{
final L2EnchantSkillLearn[] enchantSkillLearnList = getAvailableEnchantSkills(player);
for (final L2EnchantSkillLearn enchantSkillLearn : enchantSkillLearnList)
{
if (enchantSkillLearn.getId() != skill.getId())
{
continue;
}
if (enchantSkillLearn.getLevel() != skill.getLevel())
{
continue;
}
return enchantSkillLearn.getRate(player);
}
return 0;
}
public boolean isSkillAllowed(L2PcInstance player, L2Skill skill)
{
if (player.isGM())
{
return true;
}
if (_loading)
{
return true;
}
int level = skill.getLevel();
final int maxLvl = SkillTable.getInstance().getMaxLevel(skill.getId());
int hashCode = SkillTable.getSkillHashCode(skill.getId(), level);
if (_enchantSkillTrees.get(hashCode) != null)
{
level = _enchantSkillTrees.get(hashCode).getBaseLevel();
}
hashCode = SkillTable.getSkillHashCode(skill.getId(), Math.min(level, maxLvl));
if (Arrays.binarySearch(_skillsByClassIdHashCodes.get(player.getClassId().ordinal()), hashCode) >= 0)
{
return true;
}
if (Arrays.binarySearch(_allSkillsHashCodes, hashCode) >= 0)
{
return true;
}
return false;
}
}

View File

@@ -0,0 +1,325 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.instancemanager.DayNightSpawnManager;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.templates.L2NpcTemplate;
import javolution.util.FastMap;
/**
* This class ...
* @author Nightmare
* @version $Revision: 1.5.2.6.2.7 $ $Date: 2005/03/27 15:29:18 $
*/
public class SpawnTable
{
private static Logger _log = Logger.getLogger(SpawnTable.class.getName());
private static final SpawnTable _instance = new SpawnTable();
private final Map<Integer, L2Spawn> _spawntable = new FastMap<Integer, L2Spawn>().shared();
private int _npcSpawnCount;
private int _customSpawnCount;
private int _highestId;
public static SpawnTable getInstance()
{
return _instance;
}
private SpawnTable()
{
if (!Config.ALT_DEV_NO_SPAWNS)
{
fillSpawnTable();
}
}
public Map<Integer, L2Spawn> getSpawnTable()
{
return _spawntable;
}
private void fillSpawnTable()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id, count, npc_templateid, locx, locy, locz, heading, respawn_delay, loc_id, periodOfDay FROM spawnlist ORDER BY id");
ResultSet rset = statement.executeQuery())
{
L2Spawn spawnDat;
L2NpcTemplate template1;
while (rset.next())
{
template1 = NpcTable.getInstance().getTemplate(rset.getInt("npc_templateid"));
if (template1 != null)
{
if (template1.type.equalsIgnoreCase("L2SiegeGuard"))
{
// Don't spawn
}
else if (template1.type.equalsIgnoreCase("L2RaidBoss"))
{
// Don't spawn raidboss
}
else if (!Config.ALLOW_CLASS_MASTERS && template1.type.equals("L2ClassMaster"))
{
// Don't spawn class masters
}
else
{
spawnDat = new L2Spawn(template1);
spawnDat.setId(rset.getInt("id"));
spawnDat.setAmount(rset.getInt("count"));
spawnDat.setLocx(rset.getInt("locx"));
spawnDat.setLocy(rset.getInt("locy"));
spawnDat.setLocz(rset.getInt("locz"));
spawnDat.setHeading(rset.getInt("heading"));
spawnDat.setRespawnDelay(rset.getInt("respawn_delay"));
final int loc_id = rset.getInt("loc_id");
spawnDat.setLocation(loc_id);
switch (rset.getInt("periodOfDay"))
{
case 0: // default
_npcSpawnCount += spawnDat.init();
break;
case 1: // Day
DayNightSpawnManager.getInstance().addDayCreature(spawnDat);
_npcSpawnCount++;
break;
case 2: // Night
DayNightSpawnManager.getInstance().addNightCreature(spawnDat);
_npcSpawnCount++;
break;
}
_spawntable.put(spawnDat.getId(), spawnDat);
if (spawnDat.getId() > _highestId)
{
_highestId = spawnDat.getId();
}
}
}
else
{
_log.warning("SpawnTable: Data missing in NPC table for ID: " + rset.getInt("npc_templateid") + ".");
}
}
}
catch (final Exception e)
{
// problem with initializing spawn, go to next one
_log.warning("SpawnTable: Spawn could not be initialized: " + e);
}
_log.config("SpawnTable: Loaded " + _spawntable.size() + " Npc Spawn Locations.");
if (Config.CUSTOM_SPAWNLIST_TABLE)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id, count, npc_templateid, locx, locy, locz, heading, respawn_delay, loc_id, periodOfDay FROM custom_spawnlist ORDER BY id");
ResultSet rset = statement.executeQuery())
{
L2Spawn spawnDat;
L2NpcTemplate template1;
while (rset.next())
{
template1 = NpcTable.getInstance().getTemplate(rset.getInt("npc_templateid"));
if (template1 != null)
{
if (template1.type.equalsIgnoreCase("L2SiegeGuard"))
{
// Don't spawn
}
else if (template1.type.equalsIgnoreCase("L2RaidBoss"))
{
// Don't spawn raidboss
}
else if (!Config.ALLOW_CLASS_MASTERS && template1.type.equals("L2ClassMaster"))
{
// Don't spawn class masters
}
else
{
spawnDat = new L2Spawn(template1);
spawnDat.setId(rset.getInt("id"));
spawnDat.setAmount(rset.getInt("count"));
spawnDat.setLocx(rset.getInt("locx"));
spawnDat.setLocy(rset.getInt("locy"));
spawnDat.setLocz(rset.getInt("locz"));
spawnDat.setHeading(rset.getInt("heading"));
spawnDat.setRespawnDelay(rset.getInt("respawn_delay"));
spawnDat.setCustom(true);
final int loc_id = rset.getInt("loc_id");
spawnDat.setLocation(loc_id);
switch (rset.getInt("periodOfDay"))
{
case 0: // default
_customSpawnCount += spawnDat.init();
break;
case 1: // Day
DayNightSpawnManager.getInstance().addDayCreature(spawnDat);
_customSpawnCount++;
break;
case 2: // Night
DayNightSpawnManager.getInstance().addNightCreature(spawnDat);
_customSpawnCount++;
break;
}
_spawntable.put(spawnDat.getId(), spawnDat);
if (spawnDat.getId() > _highestId)
{
_highestId = spawnDat.getId();
}
}
}
else
{
_log.warning("SpawnTable: Data missing in Custom NPC table for ID: " + rset.getInt("npc_templateid") + ".");
}
}
}
catch (final Exception e)
{
// problem with initializing custom spawn, go to next one
_log.warning("SpawnTable: Custom spawn could not be initialized: " + e);
}
_log.config("CustomSpawnTable: Loaded " + _customSpawnCount + " Custom Npc Spawn Locations.");
}
if (Config.DEBUG)
{
_log.fine("SpawnTable: Spawning completed, total number of NPCs in the world: " + (_npcSpawnCount + _customSpawnCount));
}
}
public L2Spawn getTemplate(int id)
{
return _spawntable.get(id);
}
public void addNewSpawn(L2Spawn spawn, boolean storeInDb)
{
_highestId++;
spawn.setId(_highestId);
_spawntable.put(_highestId, spawn);
if (storeInDb)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO " + (spawn.isCustom() ? "custom_spawnlist" : "spawnlist") + " (id,count,npc_templateid,locx,locy,locz,heading,respawn_delay,loc_id) values(?,?,?,?,?,?,?,?,?)"))
{
statement.setInt(1, spawn.getId());
statement.setInt(2, spawn.getAmount());
statement.setInt(3, spawn.getNpcid());
statement.setInt(4, spawn.getLocx());
statement.setInt(5, spawn.getLocy());
statement.setInt(6, spawn.getLocz());
statement.setInt(7, spawn.getHeading());
statement.setInt(8, spawn.getRespawnDelay() / 1000);
statement.setInt(9, spawn.getLocation());
statement.execute();
}
catch (final Exception e)
{
// problem with storing spawn
_log.warning("SpawnTable: Could not store spawn in the DB:" + e);
}
}
}
public void deleteSpawn(L2Spawn spawn, boolean updateDb)
{
if (_spawntable.remove(spawn.getId()) == null)
{
return;
}
if (updateDb)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM " + (spawn.isCustom() ? "custom_spawnlist" : "spawnlist") + " WHERE id=?"))
{
statement.setInt(1, spawn.getId());
statement.execute();
}
catch (final Exception e)
{
// problem with deleting spawn
_log.warning("SpawnTable: Spawn " + spawn.getId() + " could not be removed from DB: " + e);
}
}
}
// just wrapper
public void reloadAll()
{
fillSpawnTable();
}
/**
* Get all the spawn of a NPC<BR>
* <BR>
* @param activeChar
* @param npcId : ID of the NPC to find.
* @param teleportIndex
*/
public void findNPCInstances(L2PcInstance activeChar, int npcId, int teleportIndex)
{
int index = 0;
for (final L2Spawn spawn : _spawntable.values())
{
if (npcId == spawn.getNpcid())
{
index++;
if (teleportIndex > -1)
{
if (teleportIndex == index)
{
activeChar.teleToLocation(spawn.getLocx(), spawn.getLocy(), spawn.getLocz(), true);
}
}
else
{
activeChar.sendMessage(index + " - " + spawn.getTemplate().name + " (" + spawn.getId() + "): " + spawn.getLocx() + " " + spawn.getLocy() + " " + spawn.getLocz());
}
}
}
if (index == 0)
{
activeChar.sendMessage("No current spawns found.");
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.LineNumberReader;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.model.actor.instance.L2StaticObjectInstance;
import javolution.util.FastMap;
public class StaticObjects
{
private static Logger _log = Logger.getLogger(StaticObjects.class.getName());
private static StaticObjects _instance;
private final Map<Integer, L2StaticObjectInstance> _staticObjects;
public static StaticObjects getInstance()
{
if (_instance == null)
{
_instance = new StaticObjects();
}
return _instance;
}
public StaticObjects()
{
_staticObjects = new FastMap<>();
parseData();
_log.config("StaticObject: Loaded " + _staticObjects.size() + " StaticObject Templates.");
}
private void parseData()
{
final File objectData = new File(Config.DATAPACK_ROOT, "data/staticobjects.csv");
try (FileReader fr = new FileReader(objectData);
BufferedReader br = new BufferedReader(fr);
LineNumberReader lnr = new LineNumberReader(br))
{
String line = null;
while ((line = lnr.readLine()) != null)
{
if ((line.trim().length() == 0) || line.startsWith("#"))
{
continue;
}
final L2StaticObjectInstance obj = parse(line);
_staticObjects.put(obj.getStaticObjectId(), obj);
}
}
catch (final FileNotFoundException e)
{
_log.warning("staticobjects.csv is missing in data folder");
}
catch (final Exception e)
{
_log.warning("error while creating StaticObjects table " + e);
}
}
public static L2StaticObjectInstance parse(String line)
{
final StringTokenizer st = new StringTokenizer(line, ";");
st.nextToken(); // Pass over static object name (not used in server)
final int id = Integer.parseInt(st.nextToken());
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int type = Integer.parseInt(st.nextToken());
final String texture = st.nextToken();
final int map_x = Integer.parseInt(st.nextToken());
final int map_y = Integer.parseInt(st.nextToken());
final L2StaticObjectInstance obj = new L2StaticObjectInstance(IdFactory.getInstance().getNextId());
obj.setType(type);
obj.setStaticObjectId(id);
obj.setXYZ(x, y, z);
obj.setMap(texture, map_x, map_y);
obj.spawnMe();
return obj;
}
}

View File

@@ -0,0 +1,120 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.io.File;
import java.util.Scanner;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2SummonItem;
import javolution.util.FastMap;
/**
* @author FBIagent
*/
public class SummonItemsData
{
private final FastMap<Integer, L2SummonItem> _summonitems;
private static SummonItemsData _instance;
public static SummonItemsData getInstance()
{
if (_instance == null)
{
_instance = new SummonItemsData();
}
return _instance;
}
public SummonItemsData()
{
_summonitems = new FastMap<>();
try (Scanner s = new Scanner(new File(Config.DATAPACK_ROOT + "/data/summon_items.csv")))
{
int lineCount = 0;
while (s.hasNextLine())
{
lineCount++;
final String line = s.nextLine();
if (line.startsWith("#"))
{
continue;
}
else if (line.isEmpty())
{
continue;
}
final String[] lineSplit = line.split(";");
boolean ok = true;
int itemID = 0, npcID = 0;
byte summonType = 0;
try
{
itemID = Integer.parseInt(lineSplit[0]);
npcID = Integer.parseInt(lineSplit[1]);
summonType = Byte.parseByte(lineSplit[2]);
}
catch (final Exception e)
{
System.out.println("Summon items data: Error in line " + lineCount + " -> incomplete/invalid data or wrong seperator!");
System.out.println(" " + line);
ok = false;
}
if (!ok)
{
continue;
}
final L2SummonItem summonitem = new L2SummonItem(itemID, npcID, summonType);
_summonitems.put(itemID, summonitem);
}
System.out.println("Summon items data: Loaded " + _summonitems.size() + " summon items.");
}
catch (final Exception e)
{
System.out.println("Summon items data: Cannot find '" + Config.DATAPACK_ROOT + "/data/summon_items.csv'");
}
}
public L2SummonItem getSummonItem(int itemId)
{
return _summonitems.get(itemId);
}
public int[] itemIDs()
{
final int size = _summonitems.size();
final int[] result = new int[size];
int i = 0;
for (final L2SummonItem si : _summonitems.values())
{
result[i] = si.getItemId();
i++;
}
return result;
}
}

View File

@@ -0,0 +1,128 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.model.L2TeleportLocation;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.3.2.2.2.3 $ $Date: 2005/03/27 15:29:18 $
*/
public class TeleportLocationTable
{
private static Logger _log = Logger.getLogger(TeleportLocationTable.class.getName());
private static TeleportLocationTable _instance;
private Map<Integer, L2TeleportLocation> _teleports;
public static TeleportLocationTable getInstance()
{
if (_instance == null)
{
_instance = new TeleportLocationTable();
}
return _instance;
}
private TeleportLocationTable()
{
reloadAll();
}
public void reloadAll()
{
_teleports = new FastMap<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT Description, id, loc_x, loc_y, loc_z, price, fornoble FROM teleport");
ResultSet rset = statement.executeQuery())
{
L2TeleportLocation teleport;
while (rset.next())
{
teleport = new L2TeleportLocation();
teleport.setTeleId(rset.getInt("id"));
teleport.setLocX(rset.getInt("loc_x"));
teleport.setLocY(rset.getInt("loc_y"));
teleport.setLocZ(rset.getInt("loc_z"));
teleport.setPrice(rset.getInt("price"));
teleport.setIsForNoble(rset.getInt("fornoble") == 1);
_teleports.put(teleport.getTeleId(), teleport);
}
_log.config("TeleportLocationTable: Loaded " + _teleports.size() + " Teleport Location Templates.");
}
catch (final Exception e)
{
_log.warning("error while creating teleport table " + e);
}
if (Config.CUSTOM_TELEPORT_TABLE)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT Description, id, loc_x, loc_y, loc_z, price, fornoble FROM custom_teleport");
ResultSet rset = statement.executeQuery())
{
L2TeleportLocation teleport;
final int _cTeleCount = _teleports.size();
while (rset.next())
{
teleport = new L2TeleportLocation();
teleport.setTeleId(rset.getInt("id"));
teleport.setLocX(rset.getInt("loc_x"));
teleport.setLocY(rset.getInt("loc_y"));
teleport.setLocZ(rset.getInt("loc_z"));
teleport.setPrice(rset.getInt("price"));
teleport.setIsForNoble(rset.getInt("fornoble") == 1);
_teleports.put(teleport.getTeleId(), teleport);
}
_log.config("TeleportLocationTable: Loaded " + (_teleports.size() - _cTeleCount) + " Custom Teleport Location Templates.");
}
catch (final Exception e)
{
_log.warning("error while creating custom teleport table " + e);
}
}
}
/**
* @param id
* @return
*/
public L2TeleportLocation getTemplate(int id)
{
return _teleports.get(id);
}
}

View File

@@ -0,0 +1,421 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.datatables;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.instancemanager.ArenaManager;
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
import com.l2jmobius.gameserver.instancemanager.OlympiadStadiumManager;
import com.l2jmobius.gameserver.instancemanager.TownManager;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.L2WorldRegion;
import com.l2jmobius.gameserver.model.zone.L2ZoneSpawn;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.form.ZoneCuboid;
import com.l2jmobius.gameserver.model.zone.form.ZoneNPoly;
import com.l2jmobius.gameserver.model.zone.type.L2ArenaZone;
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
import com.l2jmobius.gameserver.model.zone.type.L2CastleTeleportZone;
import com.l2jmobius.gameserver.model.zone.type.L2ClanHallZone;
import com.l2jmobius.gameserver.model.zone.type.L2DamageZone;
import com.l2jmobius.gameserver.model.zone.type.L2DerbyTrackZone;
import com.l2jmobius.gameserver.model.zone.type.L2EffectZone;
import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
import com.l2jmobius.gameserver.model.zone.type.L2JailZone;
import com.l2jmobius.gameserver.model.zone.type.L2MotherTreeZone;
import com.l2jmobius.gameserver.model.zone.type.L2NoHqZone;
import com.l2jmobius.gameserver.model.zone.type.L2NoLandingZone;
import com.l2jmobius.gameserver.model.zone.type.L2NoStoreZone;
import com.l2jmobius.gameserver.model.zone.type.L2OlympiadStadiumZone;
import com.l2jmobius.gameserver.model.zone.type.L2PeaceZone;
import com.l2jmobius.gameserver.model.zone.type.L2SiegeZone;
import com.l2jmobius.gameserver.model.zone.type.L2TownZone;
import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
import javolution.util.FastList;
/**
* This class manages all zone data.
* @author durgus
*/
public class ZoneTable
{
private static final Logger _log = Logger.getLogger(ZoneTable.class.getName());
// =========================================================
private static ZoneTable _instance;
public static final ZoneTable getInstance()
{
if (_instance == null)
{
_instance = new ZoneTable();
}
return _instance;
}
// =========================================================
// Data Field
// =========================================================
// Constructor
public ZoneTable()
{
_log.info("Loading zones");
load();
}
// =========================================================
// Method - Private
private final void load()
{
int zoneCount = 0;
// Get the world regions
final L2WorldRegion[][] worldRegions = L2World.getInstance().getAllWorldRegions();
// Get an sql connection here
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
// Load the zone xml
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
final File file = new File(Config.DATAPACK_ROOT + "/data/zones/zone.xml");
if (!file.exists())
{
if (Config.DEBUG)
{
_log.info("The zone.xml file is missing.");
}
return;
}
final Document doc = factory.newDocumentBuilder().parse(file);
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("zone".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
final int zoneId = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
final int minZ = Integer.parseInt(attrs.getNamedItem("minZ").getNodeValue());
final int maxZ = Integer.parseInt(attrs.getNamedItem("maxZ").getNodeValue());
final String zoneType = attrs.getNamedItem("type").getNodeValue();
final String zoneShape = attrs.getNamedItem("shape").getNodeValue();
// Create the zone
L2ZoneType temp = null;
if (zoneType.equals("FishingZone"))
{
temp = new L2FishingZone(zoneId);
}
else if (zoneType.equals("ClanHallZone"))
{
temp = new L2ClanHallZone(zoneId);
}
else if (zoneType.equals("PeaceZone"))
{
temp = new L2PeaceZone(zoneId);
}
else if (zoneType.equals("Town"))
{
temp = new L2TownZone(zoneId);
}
else if (zoneType.equals("OlympiadStadium"))
{
temp = new L2OlympiadStadiumZone(zoneId);
}
else if (zoneType.equals("SiegeZone"))
{
temp = new L2SiegeZone(zoneId);
}
else if (zoneType.equals("DamageZone"))
{
temp = new L2DamageZone(zoneId);
}
else if (zoneType.equals("Arena"))
{
temp = new L2ArenaZone(zoneId);
}
else if (zoneType.equals("MotherTree"))
{
temp = new L2MotherTreeZone(zoneId);
}
else if (zoneType.equals("EffectZone"))
{
temp = new L2EffectZone(zoneId);
}
else if (zoneType.equals("NoLandingZone"))
{
temp = new L2NoLandingZone(zoneId);
}
else if (zoneType.equals("JailZone"))
{
temp = new L2JailZone(zoneId);
}
else if (zoneType.equals("DerbyTrackZone"))
{
temp = new L2DerbyTrackZone(zoneId);
}
else if (zoneType.equals("WaterZone"))
{
temp = new L2WaterZone(zoneId);
}
else if (zoneType.equals("CastleTeleportZone"))
{
temp = new L2CastleTeleportZone(zoneId);
}
else if (zoneType.equals("NoHqZone"))
{
temp = new L2NoHqZone(zoneId);
}
else if (zoneType.equals("BossZone"))
{
temp = new L2BossZone(zoneId);
}
else if (zoneType.equals("NoStoreZone"))
{
temp = new L2NoStoreZone(zoneId);
}
// Check for unknown type
if (temp == null)
{
_log.warning("ZoneTable: No such zone type: " + zoneType);
continue;
}
// Get the zone shape from sql
try (PreparedStatement statement = con.prepareStatement("SELECT x,y FROM zone_vertices WHERE id=? ORDER BY 'order' ASC "))
{
// Set the correct query
statement.setInt(1, zoneId);
try (ResultSet rset = statement.executeQuery())
{
// Create this zone. Parsing for cuboids is a bit different than for other polygons
// cuboids need exactly 2 points to be defined. Other polygons need at least 3 (one per vertex)
if (zoneShape.equals("Cuboid"))
{
final int[] x =
{
0,
0
};
final int[] y =
{
0,
0
};
boolean successfulLoad = true;
for (int i = 0; i < 2; i++)
{
if (rset.next())
{
x[i] = rset.getInt("x");
y[i] = rset.getInt("y");
}
else
{
_log.warning("ZoneTable: Missing cuboid vertex in sql data for zone: " + zoneId);
successfulLoad = false;
break;
}
}
if (successfulLoad)
{
temp.setZone(zoneId, new ZoneCuboid(x[0], x[1], y[0], y[1], minZ, maxZ));
}
else
{
continue;
}
}
else if (zoneShape.equals("NPoly"))
{
final FastList<Integer> fl_x = new FastList<>(), fl_y = new FastList<>();
// Load the rest
while (rset.next())
{
fl_x.add(rset.getInt("x"));
fl_y.add(rset.getInt("y"));
}
// An nPoly needs to have at least 3 vertices
if ((fl_x.size() == fl_y.size()) && (fl_x.size() > 2))
{
// Create arrays
final int[] aX = new int[fl_x.size()];
final int[] aY = new int[fl_y.size()];
// This runs only at server startup so dont complain :>
for (int i = 0; i < fl_x.size(); i++)
{
aX[i] = fl_x.get(i);
aY[i] = fl_y.get(i);
}
// Create the zone
temp.setZone(zoneId, new ZoneNPoly(aX, aY, minZ, maxZ));
}
else
{
_log.warning("ZoneTable: Bad sql data for zone: " + zoneId);
continue;
}
}
else
{
_log.warning("ZoneTable: Unknown shape: " + zoneShape);
continue;
}
}
}
catch (final Exception e)
{
_log.warning("ZoneTable: Failed to load zone coordinates: " + e);
}
// Check for additional parameters
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("stat".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
final String name = attrs.getNamedItem("name").getNodeValue();
final String val = attrs.getNamedItem("val").getNodeValue();
temp.setParameter(name, val);
}
else if ("spawn".equalsIgnoreCase(cd.getNodeName()) && (temp instanceof L2ZoneSpawn))
{
attrs = cd.getAttributes();
final int spawnX = Integer.parseInt(attrs.getNamedItem("X").getNodeValue());
final int spawnY = Integer.parseInt(attrs.getNamedItem("Y").getNodeValue());
final int spawnZ = Integer.parseInt(attrs.getNamedItem("Z").getNodeValue());
final Node val = attrs.getNamedItem("isChaotic");
if ((val != null) && Boolean.parseBoolean(val.getNodeValue()))
{
((L2ZoneSpawn) temp).addChaoticSpawn(spawnX, spawnY, spawnZ);
}
else
{
((L2ZoneSpawn) temp).addSpawn(spawnX, spawnY, spawnZ);
}
}
}
// Register the zone into any world region it intersects with...
// currently 11136 test for each zone :>
int ax, ay, bx, by;
for (int x = 0; x < worldRegions.length; x++)
{
for (int y = 0; y < worldRegions[x].length; y++)
{
ax = (x - L2World.OFFSET_X) << L2World.SHIFT_BY;
bx = ((x + 1) - L2World.OFFSET_X) << L2World.SHIFT_BY;
ay = (y - L2World.OFFSET_Y) << L2World.SHIFT_BY;
by = ((y + 1) - L2World.OFFSET_Y) << L2World.SHIFT_BY;
if (temp.getZone().intersectsRectangle(ax, bx, ay, by))
{
if (Config.DEBUG)
{
_log.info("Zone (" + zoneId + ") added to: " + x + " " + y);
}
worldRegions[x][y].addZone(temp);
}
}
}
// Special managers for arenas, towns...
if (temp instanceof L2ArenaZone)
{
ArenaManager.getInstance().addArena((L2ArenaZone) temp);
}
else if (temp instanceof L2TownZone)
{
TownManager.getInstance().addTown((L2TownZone) temp);
}
else if (temp instanceof L2OlympiadStadiumZone)
{
OlympiadStadiumManager.getInstance().addStadium((L2OlympiadStadiumZone) temp);
}
else if (temp instanceof L2BossZone)
{
GrandBossManager.getInstance().addZone((L2BossZone) temp);
}
// Increase the counter
zoneCount++;
}
}
}
}
}
catch (final Exception e)
{
_log.log(Level.SEVERE, "Error while loading zones.", e);
return;
}
GrandBossManager.getInstance().initZones();
_log.info("Loaded " + zoneCount + " zones.");
}
public FastList<L2ZoneType> getZones(int x, int y)
{
final L2WorldRegion region = L2World.getInstance().getRegion(x, y);
final FastList<L2ZoneType> temp = new FastList<>();
for (final L2ZoneType zone : region.getZones())
{
if (zone.isInsideZone(x, y))
{
temp.add(zone);
}
}
return temp;
}
}

View File

@@ -0,0 +1,56 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.events;
import javolution.util.FastList;
/**
* @author Layane
*/
public class Event
{
private final FastList<EventHandler> _handlers = new FastList<>();
public void add(EventHandler handler)
{
if (!_handlers.contains(handler))
{
_handlers.add(handler);
}
}
public void remove(EventHandler handler)
{
if (handler != null)
{
_handlers.remove(handler);
}
}
public void fire(Object trigger, IEventParams params)
{
for (final EventHandler handler : _handlers)
{
handler.handler(trigger, params);
}
}
public void clear()
{
_handlers.clear();
}
}

View File

@@ -0,0 +1,47 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.events;
/**
* @author Layane
*/
public abstract class EventHandler
{
private final Object _owner;
public EventHandler(Object owner)
{
_owner = owner;
}
public final Object getOwner()
{
return _owner;
}
@Override
public final boolean equals(Object object)
{
if ((object instanceof EventHandler) && (_owner == ((EventHandler) object)._owner))
{
return true;
}
return false;
}
public abstract void handler(Object trigger, IEventParams params);
}

View File

@@ -0,0 +1,24 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.events;
/**
* @author Layane
*/
public interface IEventParams
{
}

View File

@@ -0,0 +1,111 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.geoeditorcon;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Dezmond
*/
public class GeoEditorListener extends Thread
{
private static GeoEditorListener _instance;
private static final int PORT = 9011;
private static Logger _log = Logger.getLogger(GeoEditorListener.class.getName());
private final ServerSocket _serverSocket;
private static GeoEditorThread _geoEditor;
public static GeoEditorListener getInstance()
{
if (_instance == null)
{
try
{
_instance = new GeoEditorListener();
_instance.start();
_log.info("GeoEditorListener Initialized.");
}
catch (final IOException e)
{
_log.severe("Error creating geoeditor listener! " + e.getMessage());
System.exit(1);
}
}
return _instance;
}
private GeoEditorListener() throws IOException
{
_serverSocket = new ServerSocket(PORT);
}
public GeoEditorThread getThread()
{
return _geoEditor;
}
public String getStatus()
{
if ((_geoEditor != null) && _geoEditor.isWorking())
{
return "Geoeditor connected.";
}
return "Geoeditor not connected.";
}
@Override
public void run()
{
try (Socket connection = _serverSocket.accept())
{
while (true)
{
if ((_geoEditor != null) && _geoEditor.isWorking())
{
_log.warning("Geoeditor already connected!");
connection.close();
continue;
}
_log.info("Received geoeditor connection from: " + connection.getInetAddress().getHostAddress());
_geoEditor = new GeoEditorThread(connection);
_geoEditor.start();
}
}
catch (final Exception e)
{
_log.info("GeoEditorListener: " + e.getMessage());
}
finally
{
try
{
_serverSocket.close();
}
catch (final IOException io)
{
_log.log(Level.INFO, "", io);
}
_log.warning("GeoEditorListener Closed!");
}
}
}

View File

@@ -0,0 +1,300 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.geoeditorcon;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import javolution.util.FastList;
/**
* @author Luno, Dezmond
*/
public class GeoEditorThread extends Thread
{
private static Logger _log = Logger.getLogger(GeoEditorThread.class.getName());
private boolean _working = false;
private int _mode = 0; // 0 - don't send coords, 1 - send each
// validateposition from client, 2 - send in
// intervals of _sendDelay ms.
private int _sendDelay = 1000; // default - once in second
private final Socket _geSocket;
private OutputStream _out;
private final FastList<L2PcInstance> _gms;
public GeoEditorThread(Socket ge)
{
_geSocket = ge;
_working = true;
_gms = new FastList<>();
}
@Override
public void interrupt()
{
try
{
_geSocket.close();
}
catch (final Exception e)
{
}
super.interrupt();
}
@Override
public void run()
{
try
{
_out = _geSocket.getOutputStream();
int timer = 0;
while (_working)
{
if (!isConnected())
{
_working = false;
}
if ((_mode == 2) && (timer > _sendDelay))
{
for (final L2PcInstance gm : _gms)
{
if (gm == null)
{
continue;
}
if (!gm.getClient().getConnection().isClosed())
{
sendGmPosition(gm);
}
else
{
_gms.remove(gm);
}
}
timer = 0;
}
try
{
sleep(100);
if (_mode == 2)
{
timer += 100;
}
}
catch (final Exception e)
{
}
}
}
catch (final SocketException e)
{
_log.warning("GeoEditor disconnected. " + e.getMessage());
}
catch (final Exception e)
{
e.printStackTrace();
}
finally
{
try
{
_geSocket.close();
}
catch (final Exception e)
{
}
_working = false;
}
}
public void sendGmPosition(int gx, int gy, short z)
{
if (!isConnected())
{
return;
}
try
{
synchronized (_out)
{
writeC(0x0b); // length 11 bytes!
writeC(0x01); // Cmd = save cell;
writeD(gx); // Global coord X;
writeD(gy); // Global coord Y;
writeH(z); // Coord Z;
_out.flush();
}
}
catch (final SocketException e)
{
_log.warning("GeoEditor disconnected. " + e.getMessage());
_working = false;
}
catch (final Exception e)
{
e.printStackTrace();
try
{
_geSocket.close();
}
catch (final Exception ex)
{
}
_working = false;
}
}
public void sendGmPosition(L2PcInstance _gm)
{
sendGmPosition(_gm.getX(), _gm.getY(), (short) _gm.getZ());
}
public void sendPing()
{
if (!isConnected())
{
return;
}
try
{
synchronized (_out)
{
writeC(0x01); // length 1 byte!
writeC(0x02); // Cmd = ping (dummy packet for connection
_out.flush();
}
}
catch (final SocketException e)
{
_log.warning("GeoEditor disconnected. " + e.getMessage());
_working = false;
}
catch (final Exception e)
{
e.printStackTrace();
try
{
_geSocket.close();
}
catch (final Exception ex)
{
}
_working = false;
}
}
private void writeD(int value) throws IOException
{
_out.write(value & 0xff);
_out.write((value >> 8) & 0xff);
_out.write((value >> 16) & 0xff);
_out.write((value >> 24) & 0xff);
}
private void writeH(int value) throws IOException
{
_out.write(value & 0xff);
_out.write((value >> 8) & 0xff);
}
private void writeC(int value) throws IOException
{
_out.write(value & 0xff);
}
public void setMode(int value)
{
_mode = value;
}
public void setTimer(int value)
{
if (value < 500)
{
_sendDelay = 500; // maximum - 2 times per second!
}
else if (value > 60000)
{
_sendDelay = 60000; // Minimum - 1 time per minute.
}
else
{
_sendDelay = value;
}
}
public void addGM(L2PcInstance gm)
{
if (!_gms.contains(gm))
{
_gms.add(gm);
}
}
public void removeGM(L2PcInstance gm)
{
if (_gms.contains(gm))
{
_gms.remove(gm);
}
}
public boolean isSend(L2PcInstance gm)
{
if ((_mode == 1) && _gms.contains(gm))
{
return true;
}
return false;
}
private boolean isConnected()
{
return _geSocket.isConnected() && !_geSocket.isClosed();
}
public boolean isWorking()
{
sendPing();
return _working;
}
public int getMode()
{
return _mode;
}
}

View File

@@ -0,0 +1,176 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.1.4.5 $ $Date: 2005/03/27 15:30:09 $
*/
public class AdminCommandHandler
{
private static Logger _log = Logger.getLogger(AdminCommandHandler.class.getName());
private static AdminCommandHandler _instance;
private final Map<String, IAdminCommandHandler> _datatable;
// Alt privileges setting
private static Logger _priviLog = Logger.getLogger("AltPrivilegesAdmin");
private static FastMap<String, Integer> _privileges;
public static AdminCommandHandler getInstance()
{
if (_instance == null)
{
_instance = new AdminCommandHandler();
}
return _instance;
}
private AdminCommandHandler()
{
_datatable = new FastMap<>();
}
public void registerAdminCommandHandler(IAdminCommandHandler handler)
{
final String[] ids = handler.getAdminCommandList();
for (final String id : ids)
{
if (Config.DEBUG)
{
_log.fine("Adding handler for command " + id);
}
_datatable.put(new String(id), handler);
}
}
public IAdminCommandHandler getAdminCommandHandler(String adminCommand)
{
String command = adminCommand;
if (adminCommand.indexOf(" ") != -1)
{
command = adminCommand.substring(0, adminCommand.indexOf(" "));
}
if (Config.DEBUG)
{
_log.fine("getting handler for command: " + command + " -> " + (_datatable.get(new String(command)) != null));
}
return _datatable.get(command);
}
/**
* @return
*/
public int size()
{
return _datatable.size();
}
public final boolean checkPrivileges(L2PcInstance player, String adminCommand)
{
// Only a GM can execute a admin command
if (!player.isGM())
{
return false;
}
// Skip special privileges handler?
if (!Config.ALT_PRIVILEGES_ADMIN || Config.EVERYBODY_HAS_ADMIN_RIGHTS)
{
return true;
}
if (_privileges == null)
{
_privileges = new FastMap<>();
}
String command = adminCommand;
if (adminCommand.indexOf(" ") != -1)
{
command = adminCommand.substring(0, adminCommand.indexOf(" "));
}
// The command not exists
if (!_datatable.containsKey(command))
{
return false;
}
int requireLevel = 0;
if (!_privileges.containsKey(command))
{
// Try to loaded the command config
boolean isLoaded = false;
final Properties Settings = new Properties();
try (InputStream is = new FileInputStream(Config.COMMAND_PRIVILEGES_FILE))
{
Settings.load(is);
}
catch (final Exception e)
{
}
final String stringLevel = Settings.getProperty(command);
if (stringLevel != null)
{
isLoaded = true;
requireLevel = Integer.parseInt(stringLevel);
}
// Secure level?
if (!isLoaded)
{
if (Config.ALT_PRIVILEGES_SECURE_CHECK)
{
_priviLog.info("The command '" + command + "' haven't got a entry in the configuration file. The command cannot be executed!!");
return false;
}
requireLevel = Config.ALT_PRIVILEGES_DEFAULT_LEVEL;
}
_privileges.put(command, requireLevel);
}
else
{
requireLevel = _privileges.get(command);
}
if (player.getAccessLevel() < requireLevel)
{
_priviLog.warning("<GM>" + player.getName() + ": have not access level to execute the command '" + command + "'");
return false;
}
return true;
}
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/**
* This class ...
* @version $Revision: 1.1.4.2 $ $Date: 2005/03/27 15:30:09 $
*/
public interface IAdminCommandHandler
{
/**
* this is the worker method that is called when someone uses an admin command.
* @param activeChar
* @param command
* @return command success
*/
public boolean useAdminCommand(String command, L2PcInstance activeChar);
/**
* this method is called at initialization to register all the item ids automatically
* @return all known itemIds
*/
public String[] getAdminCommandList();
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import com.l2jmobius.gameserver.model.L2ItemInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PlayableInstance;
/**
* Mother class of all itemHandlers.<BR>
* <BR>
* an IItemHandler implementation has to be stateless
* @version $Revision: 1.1.4.3 $ $Date: 2005/03/27 15:30:09 $
*/
public interface IItemHandler
{
/**
* Launch task associated to the item.
* @param playable : L2PlayableInstance designating the player
* @param item : L2ItemInstance designating the item to use
*/
public void useItem(L2PlayableInstance playable, L2ItemInstance item);
/**
* Returns the list of item IDs corresponding to the type of item.<BR>
* <BR>
* <B><I>Use :</I></U><BR>
* This method is called at initialization to register all the item IDs automatically
* @return int[] designating all itemIds for a type of item.
*/
public int[] getItemIds();
}

View File

@@ -0,0 +1,47 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import java.io.IOException;
import com.l2jmobius.gameserver.model.L2Character;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.L2Skill.SkillType;
/**
* an IItemHandler implementation has to be stateless
* @version $Revision: 1.2.2.2.2.3 $ $Date: 2005/04/03 15:55:06 $
*/
public interface ISkillHandler
{
/**
* this is the working method that is called when using a skill.
* @param activeChar
* @param skill
* @param targets
* @param crit
* @throws IOException
*/
public void useSkill(L2Character activeChar, L2Skill skill, L2Object[] targets, boolean crit) throws IOException;
/**
* this method is called at initialization to register all the item ids automatically
* @return all known itemIds
*/
public SkillType[] getSkillIds();
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/**
* This class ...
* @version $Revision: 1.1.2.1.2.2 $ $Date: 2005/03/27 15:30:10 $
*/
public interface IUserCommandHandler
{
/**
* this is the worker method that is called when someone uses an admin command.
* @param id
* @param activeChar
* @return command success
*/
public boolean useUserCommand(int id, L2PcInstance activeChar);
/**
* this method is called at initialization to register all the item ids automatically
* @return all known itemIds
*/
public int[] getUserCommandList();
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/**
* This class ...
* @version $Revision: 1.1.4.2 $ $Date: 2005/03/27 15:30:09 $
*/
public interface IVoicedCommandHandler
{
/**
* this is the worker method that is called when someone uses an admin command.
* @param activeChar
* @param command
* @param target
* @return command success
*/
public boolean useVoicedCommand(String command, L2PcInstance activeChar, String target);
/**
* this method is called at initialization to register all the item ids automatically
* @return all known itemIds
*/
public String[] getVoicedCommandList();
}

View File

@@ -0,0 +1,91 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import java.util.Map;
import java.util.TreeMap;
/**
* This class manages handlers of items
* @version $Revision: 1.1.4.3 $ $Date: 2005/03/27 15:30:09 $
*/
public class ItemHandler
{
// private static Logger _log = Logger.getLogger(ItemHandler.class.getName());
private static ItemHandler _instance;
private final Map<Integer, IItemHandler> _datatable;
/**
* Create ItemHandler if doesn't exist and returns ItemHandler
* @return ItemHandler
*/
public static ItemHandler getInstance()
{
if (_instance == null)
{
_instance = new ItemHandler();
}
return _instance;
}
/**
* Returns the number of elements contained in datatable
* @return int : Size of the datatable
*/
public int size()
{
return _datatable.size();
}
/**
* Constructor of ItemHandler
*/
private ItemHandler()
{
_datatable = new TreeMap<>();
}
/**
* Adds handler of item type in <I>datatable</I>.<BR>
* <BR>
* <B><I>Concept :</I></U><BR>
* This handler is put in <I>datatable</I> Map &lt;Integer ; IItemHandler &gt; for each ID corresponding to an item type (existing in classes of package itemhandlers) sets as key of the Map.
* @param handler (IItemHandler)
*/
public void registerItemHandler(IItemHandler handler)
{
// Get all ID corresponding to the item type of the handler
final int[] ids = handler.getItemIds();
// Add handler for each ID found
for (final int id : ids)
{
_datatable.put(new Integer(id), handler);
}
}
/**
* Returns the handler of the item
* @param itemId : int designating the itemID
* @return IItemHandler
*/
public IItemHandler getItemHandler(int itemId)
{
return _datatable.get(new Integer(itemId));
}
}

View File

@@ -0,0 +1,72 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import java.util.Map;
import java.util.TreeMap;
import com.l2jmobius.gameserver.model.L2Skill;
import com.l2jmobius.gameserver.model.L2Skill.SkillType;
/**
* This class ...
* @version $Revision: 1.1.4.4 $ $Date: 2005/04/03 15:55:06 $
*/
public class SkillHandler
{
// private static Logger _log = Logger.getLogger(SkillHandler.class.getName());
private static SkillHandler _instance;
private final Map<L2Skill.SkillType, ISkillHandler> _datatable;
public static SkillHandler getInstance()
{
if (_instance == null)
{
_instance = new SkillHandler();
}
return _instance;
}
private SkillHandler()
{
_datatable = new TreeMap<>();
}
public void registerSkillHandler(ISkillHandler handler)
{
final SkillType[] types = handler.getSkillIds();
for (final SkillType t : types)
{
_datatable.put(t, handler);
}
}
public ISkillHandler getSkillHandler(SkillType skillType)
{
return _datatable.get(skillType);
}
/**
* @return
*/
public int size()
{
return _datatable.size();
}
}

View File

@@ -0,0 +1,81 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.1.2.1.2.5 $ $Date: 2005/03/27 15:30:09 $
*/
public class UserCommandHandler
{
private static Logger _log = Logger.getLogger(UserCommandHandler.class.getName());
private static UserCommandHandler _instance;
private final Map<Integer, IUserCommandHandler> _datatable;
public static UserCommandHandler getInstance()
{
if (_instance == null)
{
_instance = new UserCommandHandler();
}
return _instance;
}
private UserCommandHandler()
{
_datatable = new FastMap<>();
}
public void registerUserCommandHandler(IUserCommandHandler handler)
{
final int[] ids = handler.getUserCommandList();
for (final int id : ids)
{
if (Config.DEBUG)
{
_log.fine("Adding handler for user command " + id);
}
_datatable.put(new Integer(id), handler);
}
}
public IUserCommandHandler getUserCommandHandler(int userCommand)
{
if (Config.DEBUG)
{
_log.fine("getting handler for user command: " + userCommand);
}
return _datatable.get(new Integer(userCommand));
}
/**
* @return
*/
public int size()
{
return _datatable.size();
}
}

View File

@@ -0,0 +1,86 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.1.4.5 $ $Date: 2005/03/27 15:30:09 $
*/
public class VoicedCommandHandler
{
private static Logger _log = Logger.getLogger(ItemHandler.class.getName());
private static VoicedCommandHandler _instance;
private final Map<String, IVoicedCommandHandler> _datatable;
public static VoicedCommandHandler getInstance()
{
if (_instance == null)
{
_instance = new VoicedCommandHandler();
}
return _instance;
}
private VoicedCommandHandler()
{
_datatable = new FastMap<>();
}
public void registerVoicedCommandHandler(IVoicedCommandHandler handler)
{
final String[] ids = handler.getVoicedCommandList();
for (final String id : ids)
{
if (Config.DEBUG)
{
_log.fine("Adding handler for command " + id);
}
_datatable.put(new String(id), handler);
}
}
public IVoicedCommandHandler getVoicedCommandHandler(String voicedCommand)
{
String command = voicedCommand;
if (voicedCommand.indexOf(" ") != -1)
{
command = voicedCommand.substring(0, voicedCommand.indexOf(" "));
}
if (Config.DEBUG)
{
_log.fine("getting handler for command: " + command + " -> " + (_datatable.get(new String(command)) != null));
}
return _datatable.get(command);
}
/**
* @return
*/
public int size()
{
return _datatable.size();
}
}

View File

@@ -0,0 +1,437 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler.admincommandhandlers;
import java.util.StringTokenizer;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.Olympiad;
import com.l2jmobius.gameserver.cache.HtmCache;
import com.l2jmobius.gameserver.datatables.GmListTable;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.datatables.NpcTable;
import com.l2jmobius.gameserver.datatables.NpcWalkerRoutesTable;
import com.l2jmobius.gameserver.datatables.SkillTable;
import com.l2jmobius.gameserver.datatables.TeleportLocationTable;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
import com.l2jmobius.gameserver.instancemanager.Manager;
import com.l2jmobius.gameserver.instancemanager.QuestManager;
import com.l2jmobius.gameserver.model.EventEngine;
import com.l2jmobius.gameserver.model.L2Multisell;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
import com.l2jmobius.gameserver.network.serverpackets.SignsSky;
import com.l2jmobius.gameserver.network.serverpackets.SunRise;
import com.l2jmobius.gameserver.network.serverpackets.SunSet;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* This class handles following admin commands: - admin = shows menu
* @version $Revision: 1.3.2.1.2.4 $ $Date: 2005/04/11 10:06:06 $
*/
public class AdminAdmin implements IAdminCommandHandler
{
private static String[] _adminCommands =
{
"admin_admin",
"admin_play_sounds",
"admin_play_sound",
"admin_gmliston",
"admin_gmlistoff",
"admin_silence",
"admin_atmosphere",
"admin_diet",
"admin_tradeoff",
"admin_reload",
"admin_set",
"admin_saveolymp",
"admin_endolympiad",
"admin_sethero",
"admin_setnoble"
};
private static final int REQUIRED_LEVEL = Config.GM_MENU;
@Override
public boolean useAdminCommand(String command, L2PcInstance activeChar)
{
if (!Config.ALT_PRIVILEGES_ADMIN)
{
if (!(checkLevel(activeChar.getAccessLevel()) && activeChar.isGM()))
{
return false;
}
}
if (command.equals("admin_admin"))
{
showMainPage(activeChar);
}
else if (command.equals("admin_play_sounds"))
{
AdminHelpPage.showHelpPage(activeChar, "songs/songs.htm");
}
else if (command.startsWith("admin_play_sounds"))
{
try
{
AdminHelpPage.showHelpPage(activeChar, "songs/songs" + command.substring(17) + ".htm");
}
catch (final StringIndexOutOfBoundsException e)
{
}
}
else if (command.startsWith("admin_play_sound"))
{
try
{
playAdminSound(activeChar, command.substring(17));
}
catch (final StringIndexOutOfBoundsException e)
{
}
}
else if (command.startsWith("admin_gmliston"))
{
GmListTable.getInstance().showGm(activeChar);
activeChar.sendMessage("Registered into gm list.");
}
else if (command.startsWith("admin_gmlistoff"))
{
GmListTable.getInstance().hideGm(activeChar);
activeChar.sendMessage("Removed from gm list.");
}
else if (command.startsWith("admin_silence"))
{
if (activeChar.getMessageRefusal()) // already in message refusal mode
{
activeChar.setMessageRefusal(false);
activeChar.sendPacket(new SystemMessage(SystemMessage.MESSAGE_ACCEPTANCE_MODE));
}
else
{
activeChar.setMessageRefusal(true);
activeChar.sendPacket(new SystemMessage(SystemMessage.MESSAGE_REFUSAL_MODE));
}
}
else if (command.startsWith("admin_saveolymp"))
{
try
{
Olympiad.getInstance().save();
activeChar.sendMessage("Olympiad data saved!!");
}
catch (final Exception e)
{
e.printStackTrace();
}
}
else if (command.startsWith("admin_endolympiad"))
{
try
{
Olympiad.getInstance().manualSelectHeroes();
activeChar.sendMessage("Heroes were formed.");
}
catch (final Exception e)
{
e.printStackTrace();
}
}
else if (command.startsWith("admin_sethero"))
{
L2PcInstance target = activeChar;
if ((activeChar.getTarget() != null) && (activeChar.getTarget() instanceof L2PcInstance))
{
target = (L2PcInstance) activeChar.getTarget();
}
target.setHero(target.isHero() ? false : true);
target.broadcastUserInfo();
}
else if (command.startsWith("admin_setnoble"))
{
L2PcInstance target = activeChar;
if ((activeChar.getTarget() != null) && (activeChar.getTarget() instanceof L2PcInstance))
{
target = (L2PcInstance) activeChar.getTarget();
}
target.setNoble(target.isNoble() ? false : true);
if (target.isNoble())
{
activeChar.sendMessage(target.getName() + " has gained Noblesse status.");
}
else
{
activeChar.sendMessage(target.getName() + " has lost Noblesse status.");
}
}
else if (command.startsWith("admin_atmosphere"))
{
try
{
final StringTokenizer st = new StringTokenizer(command);
st.nextToken();
final String type = st.nextToken();
final String state = st.nextToken();
adminAtmosphere(type, state, activeChar);
}
catch (final Exception ex)
{
}
}
else if (command.startsWith("admin_diet"))
{
try
{
if (!activeChar.getDietMode())
{
activeChar.setDietMode(true);
activeChar.sendMessage("Diet mode on.");
}
else
{
activeChar.setDietMode(false);
activeChar.sendMessage("Diet mode off.");
}
activeChar.refreshOverloaded();
}
catch (final Exception ex)
{
}
}
else if (command.startsWith("admin_tradeoff"))
{
try
{
final String mode = command.substring(15);
if (mode.equalsIgnoreCase("on"))
{
activeChar.setTradeRefusal(true);
activeChar.sendMessage("Tradeoff enabled.");
}
else if (mode.equalsIgnoreCase("off"))
{
activeChar.setTradeRefusal(false);
activeChar.sendMessage("Tradeoff disabled.");
}
}
catch (final Exception ex)
{
if (activeChar.getTradeRefusal())
{
activeChar.sendMessage("Tradeoff currently enabled.");
}
else
{
activeChar.sendMessage("Tradeoff currently disabled.");
}
}
}
else if (command.startsWith("admin_reload"))
{
final StringTokenizer st = new StringTokenizer(command);
st.nextToken();
try
{
final String type = st.nextToken();
if (type.startsWith("multisell"))
{
L2Multisell.getInstance().reload();
activeChar.sendMessage("All Multisells have been reloaded.");
}
else if (type.startsWith("teleport"))
{
TeleportLocationTable.getInstance().reloadAll();
activeChar.sendMessage("Teleport location table has been reloaded.");
}
else if (type.startsWith("skill"))
{
SkillTable.getInstance().reload();
activeChar.sendMessage("All Skills have been reloaded.");
}
else if (type.startsWith("npc"))
{
NpcTable.getInstance().reloadAllNpc();
activeChar.sendMessage("All NPCs have been reloaded.");
}
else if (type.startsWith("htm"))
{
HtmCache.getInstance().reload();
activeChar.sendMessage("Cache[HTML]: " + HtmCache.getInstance().getMemoryUsage() + " megabytes on " + HtmCache.getInstance().getLoadedFiles() + " files loaded.");
}
else if (type.startsWith("item"))
{
ItemTable.getInstance().reload();
activeChar.sendMessage("All Item templates have been reloaded.");
}
else if (type.startsWith("config"))
{
Config.load();
activeChar.sendMessage("All config settings have been reload");
}
else if (type.startsWith("instancemanager"))
{
Manager.reloadAll();
activeChar.sendMessage("All instance managers have been reloaded.");
}
else if (type.startsWith("npcwalker"))
{
NpcWalkerRoutesTable.getInstance().load();
activeChar.sendMessage("All NPC walker routes have been reloaded.");
}
else if (type.startsWith("quest"))
{
QuestManager.getInstance().reloadAllQuests();
activeChar.sendMessage("All Quests have been reloaded.");
}
else if (type.startsWith("event"))
{
EventEngine.load();
activeChar.sendMessage("All Events have been reloaded.");
}
}
catch (final Exception e)
{
activeChar.sendMessage("Usage: //reload <multisell|skill|npc|htm|item|instancemanager>");
}
}
else if (command.startsWith("admin_set"))
{
final StringTokenizer st = new StringTokenizer(command);
st.nextToken();
try
{
final String[] parameter = st.nextToken().split("=");
final String pName = parameter[0].trim();
final String pValue = parameter[1].trim();
if (Config.setParameterValue(pName, pValue))
{
activeChar.sendMessage("Parameter set succesfully.");
}
else
{
activeChar.sendMessage("Invalid parameter!");
}
}
catch (final Exception e)
{
activeChar.sendMessage("Usage: //set parameter=value");
}
}
return true;
}
@Override
public String[] getAdminCommandList()
{
return _adminCommands;
}
private boolean checkLevel(int level)
{
return (level >= REQUIRED_LEVEL);
}
/**
* @param type - atmosphere type (signssky,sky)
* @param state - atmosphere state(night,day)
* @param activeChar
*/
public void adminAtmosphere(String type, String state, L2PcInstance activeChar)
{
L2GameServerPacket packet = null;
if (type.equals("signsky"))
{
if (state.equals("dawn"))
{
packet = new SignsSky(2);
}
else if (state.equals("dusk"))
{
packet = new SignsSky(1);
}
}
else if (type.equals("sky"))
{
if (state.equals("night"))
{
packet = new SunSet();
}
else if (state.equals("day"))
{
packet = new SunRise();
}
}
else
{
activeChar.sendMessage("Only sky and signsky atmosphere type allowed, damn u!");
}
if (packet != null)
{
for (final L2PcInstance player : L2World.getInstance().getAllPlayers())
{
player.sendPacket(packet);
}
}
}
public void playAdminSound(L2PcInstance activeChar, String sound)
{
final PlaySound _snd = new PlaySound(1, sound, 0, 0, 0, 0, 0);
activeChar.sendPacket(_snd);
activeChar.broadcastPacket(_snd);
showMainPage(activeChar);
activeChar.sendMessage("Playing " + sound + ".");
}
public void showMainPage(L2PcInstance activeChar)
{
final NpcHtmlMessage html = new NpcHtmlMessage(5);
html.setFile("data/html/admin/adminpanel.htm");
activeChar.sendPacket(html);
}
}

View File

@@ -0,0 +1,136 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler.admincommandhandlers;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.Announcements;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.taskmanager.AutoAnnounceTaskManager;
/**
* This class handles following admin commands: - announce text = announces text to all players - list_announcements = show menu - reload_announcements = reloads announcements from txt file - announce_announcements = announce all stored announcements to all players - add_announcement text = adds
* text to startup announcements - del_announcement id = deletes announcement with respective id
* @version $Revision: 1.4.4.5 $ $Date: 2005/04/11 10:06:06 $
*/
public class AdminAnnouncements implements IAdminCommandHandler
{
private static String[] _adminCommands =
{
"admin_list_announcements",
"admin_reload_announcements",
"admin_announce_announcements",
"admin_add_announcement",
"admin_del_announcement",
"admin_announce",
"admin_announce_menu",
"admin_reload_autoannounce"
};
private static final int REQUIRED_LEVEL = Config.GM_ANNOUNCE;
@Override
public boolean useAdminCommand(String command, L2PcInstance activeChar)
{
if (!Config.ALT_PRIVILEGES_ADMIN)
{
if (!(checkLevel(activeChar.getAccessLevel()) && activeChar.isGM()))
{
return false;
}
}
if (command.equals("admin_list_announcements"))
{
Announcements.getInstance().listAnnouncements(activeChar);
}
else if (command.equals("admin_reload_announcements"))
{
Announcements.getInstance().loadAnnouncements();
Announcements.getInstance().listAnnouncements(activeChar);
}
else if (command.startsWith("admin_announce_menu"))
{
final Announcements sys = new Announcements();
sys.handleAnnounce(command, 20);
Announcements.getInstance().listAnnouncements(activeChar);
}
else if (command.equals("admin_announce_announcements"))
{
for (final L2PcInstance player : L2World.getInstance().getAllPlayers())
{
Announcements.getInstance().showAnnouncements(player);
}
Announcements.getInstance().listAnnouncements(activeChar);
}
else if (command.startsWith("admin_add_announcement"))
{
// FIXME the player can send only 16 chars (if you try to send more it sends null), remove this function or not?
if (!command.equals("admin_add_announcement"))
{
try
{
final String val = command.substring(23);
Announcements.getInstance().addAnnouncement(val);
Announcements.getInstance().listAnnouncements(activeChar);
}
catch (final StringIndexOutOfBoundsException e)
{
// ignore errors
}
}
}
else if (command.startsWith("admin_del_announcement"))
{
try
{
final int val = new Integer(command.substring(23)).intValue();
Announcements.getInstance().delAnnouncement(val);
Announcements.getInstance().listAnnouncements(activeChar);
}
catch (final StringIndexOutOfBoundsException e)
{
}
}
else if (command.startsWith("admin_announce")) // Command is admin announce
{
// Call method from another class
final Announcements sys = new Announcements();
sys.handleAnnounce(command, 15);
}
else if (command.startsWith("admin_reload_autoannounce"))
{
AutoAnnounceTaskManager.getInstance().restore();
activeChar.sendMessage("AutoAnnouncement(s) Reloaded.");
}
return true;
}
@Override
public String[] getAdminCommandList()
{
return _adminCommands;
}
private boolean checkLevel(int level)
{
return (level >= REQUIRED_LEVEL);
}
}

View File

@@ -0,0 +1,64 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler.admincommandhandlers;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.communitybbs.Manager.AdminBBSManager;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
public class AdminBBS implements IAdminCommandHandler
{
private static String[] _adminCommands =
{
"admin_bbs"
};
private static final int REQUIRED_LEVEL = Config.GM_MIN;
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.handler.IAdminCommandHandler#useAdminCommand(java.lang.String, com.l2jmobius.gameserver.model.actor.instance.L2PcInstance)
*/
@Override
public boolean useAdminCommand(String command, L2PcInstance activeChar)
{
if (!Config.ALT_PRIVILEGES_ADMIN)
{
if (!(checkLevel(activeChar.getAccessLevel()) && activeChar.isGM()))
{
return false;
}
}
AdminBBSManager.getInstance().parsecmd(command, activeChar);
return true;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.handler.IAdminCommandHandler#getAdminCommandList()
*/
@Override
public String[] getAdminCommandList()
{
return _adminCommands;
}
private boolean checkLevel(int level)
{
return (level >= REQUIRED_LEVEL);
}
}

View File

@@ -0,0 +1,266 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler.admincommandhandlers;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import com.l2jmobius.Config;
import com.l2jmobius.L2DatabaseFactory;
import com.l2jmobius.gameserver.LoginServerThread;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
import com.l2jmobius.gameserver.model.GMAudit;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/**
* This class handles following admin commands: - kill = kills target L2Character
* @version $Revision: 1.1.6.3 $ $Date: 2005/04/11 10:06:06 $
*/
public class AdminBan implements IAdminCommandHandler
{
// private static Logger _log = Logger.getLogger(AdminBan.class.getName());
private static String[] _adminCommands =
{
"admin_ban",
"admin_unban",
"admin_jail",
"admin_unjail"
};
@Override
public boolean useAdminCommand(String command, L2PcInstance activeChar)
{
if (!Config.ALT_PRIVILEGES_ADMIN)
{
if (activeChar.getAccessLevel() < Config.GM_BAN)
{
return false;
}
}
final StringTokenizer st = new StringTokenizer(command);
st.nextToken();
String player = "";
L2PcInstance plyr = null;
if (command.startsWith("admin_ban"))
{
try
{
player = st.nextToken();
plyr = L2World.getInstance().getPlayer(player);
}
catch (final Exception e)
{
final L2Object target = activeChar.getTarget();
if ((target != null) && (target instanceof L2PcInstance))
{
plyr = (L2PcInstance) target;
}
else
{
activeChar.sendMessage("Wrong parameter or target.");
}
}
if ((plyr != null) && (plyr == activeChar))
{
activeChar.sendMessage("You cannot use it on yourself.");
}
else if (plyr == null)
{
LoginServerThread.getInstance().sendAccessLevel(player, -100);
activeChar.sendMessage("This player is not ingame, so an account ban request was sent for " + player + " in case this name belongs to an account.");
}
else
{
plyr.setAccountAccesslevel(-100);
activeChar.sendMessage("Account of " + plyr.getName() + " was banned.");
plyr.logout();
}
}
else if (command.startsWith("admin_unban"))
{
try
{
player = st.nextToken();
LoginServerThread.getInstance().sendAccessLevel(player, 0);
activeChar.sendMessage("Unban request was sent for account " + player + ".");
}
catch (final Exception e)
{
activeChar.sendMessage("Usage: //unban <account_name>");
if (Config.DEBUG)
{
e.printStackTrace();
}
}
}
else if (command.startsWith("admin_jail"))
{
try
{
player = st.nextToken();
int delay = 0;
try
{
delay = Integer.parseInt(st.nextToken());
}
catch (final NumberFormatException nfe)
{
activeChar.sendMessage("Usage: //jail <charname> [penalty_minutes]");
}
catch (final NoSuchElementException nsee)
{
}
final L2PcInstance playerObj = L2World.getInstance().getPlayer(player);
if (playerObj != null)
{
playerObj.setInJail(true, delay);
activeChar.sendMessage("Character " + player + " has been jailed for " + (delay > 0 ? delay + " minutes." : "ever!"));
}
else
{
jailOfflinePlayer(activeChar, player, delay);
}
}
catch (final NoSuchElementException nsee)
{
activeChar.sendMessage("Usage: //jail <charname> [penalty_minutes]");
}
catch (final Exception e)
{
if (Config.DEBUG)
{
e.printStackTrace();
}
}
}
else if (command.startsWith("admin_unjail"))
{
try
{
player = st.nextToken();
final L2PcInstance playerObj = L2World.getInstance().getPlayer(player);
if (playerObj != null)
{
playerObj.setInJail(false, 0);
activeChar.sendMessage("Character " + player + " removed from jail.");
}
else
{
unjailOfflinePlayer(activeChar, player);
}
}
catch (final NoSuchElementException nsee)
{
activeChar.sendMessage("Specify a character name.");
}
catch (final Exception e)
{
if (Config.DEBUG)
{
e.printStackTrace();
}
}
}
GMAudit.auditGMAction(activeChar.getName(), command, player, "");
return true;
}
private void jailOfflinePlayer(L2PcInstance activeChar, String name, int delay)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("UPDATE characters SET x=?, y=?, z=?, in_jail=?, jail_timer=? WHERE char_name=?"))
{
statement.setInt(1, -114356);
statement.setInt(2, -249645);
statement.setInt(3, -2984);
statement.setInt(4, 1);
statement.setLong(5, delay * 60000);
statement.setString(6, name);
statement.execute();
final int count = statement.getUpdateCount();
if (count == 0)
{
activeChar.sendMessage("Character not found!");
}
else
{
activeChar.sendMessage("Character " + name + " jailed for " + (delay > 0 ? delay + " minutes." : "ever!"));
}
}
catch (final SQLException se)
{
activeChar.sendMessage("SQLException while jailing player");
if (Config.DEBUG)
{
se.printStackTrace();
}
}
}
private void unjailOfflinePlayer(L2PcInstance activeChar, String name)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("UPDATE characters SET x=?, y=?, z=?, in_jail=?, jail_timer=? WHERE char_name=?"))
{
statement.setInt(1, 17836);
statement.setInt(2, 170178);
statement.setInt(3, -3507);
statement.setInt(4, 0);
statement.setLong(5, 0);
statement.setString(6, name);
statement.execute();
final int count = statement.getUpdateCount();
if (count == 0)
{
activeChar.sendMessage("Character not found!");
}
else
{
activeChar.sendMessage("Character " + name + " removed from jail.");
}
}
catch (final SQLException se)
{
activeChar.sendMessage("SQLException while jailing player.");
if (Config.DEBUG)
{
se.printStackTrace();
}
}
}
@Override
public String[] getAdminCommandList()
{
return _adminCommands;
}
}

View File

@@ -0,0 +1,145 @@
/*
* This file is part of the L2J Mobius project.
*
* 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 com.l2jmobius.gameserver.handler.admincommandhandlers;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
import com.l2jmobius.gameserver.model.GMAudit;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/**
* This class handles following admin commands: - admin_banchat = Imposes a chat ban on the specified player/target. - admin_unbanchat = Removes any chat ban on the specified player/target. Uses: admin_banchat [<player_name>] [<ban_duration>] admin_unbanchat [<player_name>] If <player_name> is not
* specified, the current target player is used.
* @version $Revision: 1.1.6.3 $ $Date: 2005/04/11 10:06:06 $
*/
public class AdminBanChat implements IAdminCommandHandler
{
// private static Logger _log = Logger.getLogger(AdminBan.class.getName());
private static String[] _adminCommands =
{
"admin_banchat",
"admin_unbanchat"
};
private static final int REQUIRED_LEVEL = Config.GM_BAN_CHAT;
@Override
public boolean useAdminCommand(String command, L2PcInstance activeChar)
{
if (!Config.ALT_PRIVILEGES_ADMIN)
{
if (!(checkLevel(activeChar.getAccessLevel())))
{
return false;
}
}
final String[] cmdParams = command.split(" ");
long banLength = -1;
L2Object targetObject = null;
L2PcInstance targetPlayer = null;
if (cmdParams.length > 1)
{
targetPlayer = L2World.getInstance().getPlayer(cmdParams[1]);
if (cmdParams.length > 2)
{
try
{
banLength = Integer.parseInt(cmdParams[2]) * 60000;
}
catch (final NumberFormatException nfe)
{
}
}
}
else
{
if (activeChar.getTarget() != null)
{
targetObject = activeChar.getTarget();
if ((targetObject != null) && (targetObject instanceof L2PcInstance))
{
targetPlayer = (L2PcInstance) targetObject;
}
}
}
if (targetPlayer == null)
{
activeChar.sendMessage("Incorrect parameter or target.");
return false;
}
if (command.startsWith("admin_banchat"))
{
String banLengthStr = "";
if (banLength > -1)
{
targetPlayer.setChatUnbanTask(ThreadPoolManager.getInstance().scheduleGeneral(new SchedChatUnban(targetPlayer, activeChar), banLength));
banLengthStr = " for " + banLength + " seconds.";
}
activeChar.sendMessage(targetPlayer.getName() + " is now chat banned" + banLengthStr + ".");
targetPlayer.setChatBanned(true);
}
else if (command.startsWith("admin_unbanchat"))
{
activeChar.sendMessage(targetPlayer.getName() + "'s chat ban has now been lifted.");
targetPlayer.setChatBanned(false);
}
GMAudit.auditGMAction(activeChar.getName(), command, targetPlayer.getName(), "");
return true;
}
@Override
public String[] getAdminCommandList()
{
return _adminCommands;
}
private boolean checkLevel(int level)
{
return (level >= REQUIRED_LEVEL);
}
private class SchedChatUnban implements Runnable
{
L2PcInstance _player;
@SuppressWarnings("unused")
L2PcInstance _banner;
protected SchedChatUnban(L2PcInstance player, L2PcInstance banner)
{
_player = player;
_banner = banner;
}
@Override
public void run()
{
_player.setChatBanned(false);
}
}
}

Some files were not shown because too many files have changed in this diff Show More