Dropped MMOCore.

This commit is contained in:
MobiusDevelopment
2021-04-13 09:22:54 +00:00
parent 46ae40bd54
commit 5d89a8ad18
1202 changed files with 23827 additions and 22497 deletions

View File

@@ -18,8 +18,6 @@ package org.l2jmobius;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
@@ -27,26 +25,37 @@ import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.UnknownHostException;
import java.net.Inet6Address;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.IntStream;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.l2jmobius.commons.enums.ServerMode;
import org.l2jmobius.commons.util.ClassMasterSettings;
import org.l2jmobius.commons.util.IXmlReader;
import org.l2jmobius.commons.util.PropertiesParser;
import org.l2jmobius.commons.util.StringUtil;
import org.l2jmobius.gameserver.enums.GeoType;
import org.l2jmobius.gameserver.model.olympiad.OlympiadPeriod;
import org.l2jmobius.gameserver.util.FloodProtectorConfig;
import org.l2jmobius.gameserver.util.Util;
import org.l2jmobius.loginserver.LoginController;
public class Config
{
@@ -59,6 +68,7 @@ public class Config
// standard
private static final String FILTER_FILE = "./config/chatfilter.txt";
private static final String HEXID_FILE = "./config/hexid.txt";
private static final String IPCONFIG_FILE = "./config/ipconfig.xml";
// main
private static final String ACCESS_CONFIG_FILE = "./config/main/Access.ini";
private static final String CHARACTER_CONFIG_FILE = "./config/main/Character.ini";
@@ -103,15 +113,10 @@ public class Config
private static final String EVENT_REBIRTH_CONFIG_FILE = "./config/custom/Rebirth.ini";
private static final String EVENT_WEDDING_CONFIG_FILE = "./config/custom/Wedding.ini";
// login
private static final String LOGIN_CONFIG_FILE = "./config/main/LoginServer.ini";
// others
private static final String BANNED_IP_FILE = "./config/others/banned_ip.cfg";
public static final String SERVER_NAME_FILE = "./config/others/servername.xml";
// legacy
private static final String LEGACY_BANNED_IP = "./config/banned_ip.cfg";
private static final String LOGIN_CONFIG_FILE = "./config/LoginServer.ini";
// --------------------------------------------------
// Constants
// Variable Definitions
// --------------------------------------------------
public static final String EOL = System.lineSeparator();
@@ -137,9 +142,6 @@ public class Config
public static int TRADE_PVP_AMOUNT;
public static boolean GLOBAL_CHAT_WITH_PVP;
public static int GLOBAL_PVP_AMOUNT;
public static int BRUT_AVG_TIME;
public static int BRUT_LOGON_ATTEMPTS;
public static int BRUT_BAN_IP_TIME;
public static boolean LOGIN_SERVER_SCHEDULE_RESTART;
public static long LOGIN_SERVER_SCHEDULE_RESTART_TIME;
public static int MAX_CHAT_LENGTH;
@@ -204,8 +206,6 @@ public class Config
public static boolean HIGH_RATE_SERVER_DROPS;
public static boolean FORCE_COMPLETE_STATUS_UPDATE;
public static int PORT_GAME;
public static String GAMESERVER_HOSTNAME;
public static String DATABASE_DRIVER;
public static String DATABASE_URL;
public static String DATABASE_LOGIN;
@@ -1149,10 +1149,12 @@ public class Config
public static String LOGIN_BIND_ADDRESS;
public static int LOGIN_TRY_BEFORE_BAN;
public static int LOGIN_BLOCK_AFTER_BAN;
public static String GAMESERVER_HOSTNAME;
public static int PORT_GAME;
public static int GAME_SERVER_LOGIN_PORT;
public static String GAME_SERVER_LOGIN_HOST;
public static String INTERNAL_HOSTNAME;
public static String EXTERNAL_HOSTNAME;
public static List<String> GAME_SERVER_SUBNETS;
public static List<String> GAME_SERVER_HOSTS;
public static int REQUEST_ID;
public static boolean ACCEPT_ALTERNATE_ID;
public static File DATAPACK_ROOT;
@@ -1164,6 +1166,7 @@ public class Config
public static int MAX_PROTOCOL_REVISION;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int INSTANT_THREAD_POOL_COUNT;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static String CNAME_TEMPLATE;
public static String PET_NAME_TEMPLATE;
public static String CLAN_NAME_TEMPLATE;
@@ -1180,9 +1183,7 @@ public class Config
public static int PRECAUTIONARY_RESTART_PERCENTAGE;
public static int PRECAUTIONARY_RESTART_DELAY;
public static int IP_UPDATE_TIME;
public static boolean SHOW_LICENCE;
public static boolean FORCE_GGAUTH;
public static boolean FLOOD_PROTECTION;
public static int FAST_CONNECTION_LIMIT;
public static int NORMAL_CONNECTION_TIME;
@@ -1190,21 +1191,6 @@ public class Config
public static int MAX_CONNECTION_PER_IP;
public static boolean ACCEPT_NEW_GAMESERVER;
public static boolean AUTO_CREATE_ACCOUNTS;
public static String NETWORK_IP_LIST;
public static long SESSION_TTL;
public static int MAX_LOGINSESSIONS;
/** MMO settings */
public static final int MMO_SELECTOR_SLEEP_TIME = 20; // default 20
public static final int MMO_MAX_SEND_PER_PASS = 80; // default 80
public static final int MMO_MAX_READ_PER_PASS = 80; // default 80
public static final int MMO_HELPER_BUFFER_COUNT = 20; // default 20
/** Client Packets Queue settings */
public static final int CLIENT_PACKET_QUEUE_SIZE = 14; // default MMO_MAX_READ_PER_PASS + 2
/** Packet handler settings */
public static final boolean PACKET_HANDLER_DEBUG = false;
public static void loadAccessConfig()
{
@@ -1227,12 +1213,11 @@ public class Config
public static void loadServerConfig()
{
final PropertiesParser serverConfig = new PropertiesParser(SERVER_CONFIG_FILE);
GAMESERVER_HOSTNAME = serverConfig.getString("GameserverHostname", "");
GAMESERVER_HOSTNAME = serverConfig.getString("GameserverHostname", "0.0.0.0");
PORT_GAME = serverConfig.getInt("GameserverPort", 7777);
EXTERNAL_HOSTNAME = serverConfig.getString("ExternalHostname", "*");
INTERNAL_HOSTNAME = serverConfig.getString("InternalHostname", "*");
GAME_SERVER_LOGIN_PORT = serverConfig.getInt("LoginPort", 9014);
GAME_SERVER_LOGIN_HOST = serverConfig.getString("LoginHost", "127.0.0.1");
DATABASE_DRIVER = serverConfig.getString("Driver", "org.mariadb.jdbc.Driver");
DATABASE_URL = serverConfig.getString("URL", "jdbc:mariadb://localhost/");
DATABASE_LOGIN = serverConfig.getString("Login", "root");
@@ -1264,6 +1249,7 @@ public class Config
}
SCHEDULED_THREAD_POOL_COUNT = serverConfig.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverConfig.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverConfig.getInt("UrgentPacketThreadCoreSize", 20);
CNAME_TEMPLATE = serverConfig.getString("CnameTemplate", ".*");
PET_NAME_TEMPLATE = serverConfig.getString("PetNameTemplate", ".*");
CLAN_NAME_TEMPLATE = serverConfig.getString("ClanNameTemplate", ".*");
@@ -2991,15 +2977,24 @@ public class Config
public static void loadLoginStartConfig()
{
final PropertiesParser serverSettings = new PropertiesParser(LOGIN_CONFIG_FILE);
GAME_SERVER_LOGIN_HOST = serverSettings.getString("LoginHostname", "*");
GAME_SERVER_LOGIN_HOST = serverSettings.getString("LoginHostname", "127.0.0.1");
GAME_SERVER_LOGIN_PORT = serverSettings.getInt("LoginPort", 9013);
LOGIN_BIND_ADDRESS = serverSettings.getString("LoginserverHostname", "*");
LOGIN_BIND_ADDRESS = serverSettings.getString("LoginserverHostname", "0.0.0.0");
PORT_LOGIN = serverSettings.getInt("LoginserverPort", 2106);
try
{
DATAPACK_ROOT = new File(serverSettings.getString("DatapackRoot", ".").replaceAll("\\\\", "/")).getCanonicalFile();
}
catch (IOException e)
{
LOGGER.log(Level.WARNING, "Error setting datapack root!", e);
DATAPACK_ROOT = new File(".");
}
ACCEPT_NEW_GAMESERVER = serverSettings.getBoolean("AcceptNewGameServer", true);
LOGIN_TRY_BEFORE_BAN = serverSettings.getInt("LoginTryBeforeBan", 10);
LOGIN_BLOCK_AFTER_BAN = serverSettings.getInt("LoginBlockAfterBan", 600);
INTERNAL_HOSTNAME = serverSettings.getString("InternalHostname", "localhost");
EXTERNAL_HOSTNAME = serverSettings.getString("ExternalHostname", "localhost");
LOGIN_SERVER_SCHEDULE_RESTART = serverSettings.getBoolean("LoginRestartSchedule", false);
LOGIN_SERVER_SCHEDULE_RESTART_TIME = serverSettings.getLong("LoginRestartTime", 24);
DATABASE_DRIVER = serverSettings.getString("Driver", "org.mariadb.jdbc.Driver");
DATABASE_URL = serverSettings.getString("URL", "jdbc:mariadb://localhost/l2jdb");
DATABASE_LOGIN = serverSettings.getString("Login", "root");
@@ -3009,115 +3004,13 @@ public class Config
MYSQL_BIN_PATH = serverSettings.getString("MySqlBinLocation", "C:/xampp/mysql/bin/");
BACKUP_PATH = serverSettings.getString("BackupPath", "../backup/");
BACKUP_DAYS = serverSettings.getInt("BackupDays", 30);
BRUT_AVG_TIME = serverSettings.getInt("BrutAvgTime", 30); // in Seconds
BRUT_LOGON_ATTEMPTS = serverSettings.getInt("BrutLogonAttempts", 15);
BRUT_BAN_IP_TIME = serverSettings.getInt("BrutBanIpTime", 900); // in Seconds
LOGIN_SERVER_SCHEDULE_RESTART = serverSettings.getBoolean("LoginRestartSchedule", false);
LOGIN_SERVER_SCHEDULE_RESTART_TIME = serverSettings.getLong("LoginRestartTime", 24);
SHOW_LICENCE = serverSettings.getBoolean("ShowLicence", false);
IP_UPDATE_TIME = serverSettings.getInt("IpUpdateTime", 15);
FORCE_GGAUTH = serverSettings.getBoolean("ForceGGAuth", false);
AUTO_CREATE_ACCOUNTS = serverSettings.getBoolean("AutoCreateAccounts", true);
FLOOD_PROTECTION = serverSettings.getBoolean("EnableFloodProtection", true);
FAST_CONNECTION_LIMIT = serverSettings.getInt("FastConnectionLimit", 15);
NORMAL_CONNECTION_TIME = serverSettings.getInt("NormalConnectionTime", 700);
FAST_CONNECTION_TIME = serverSettings.getInt("FastConnectionTime", 350);
MAX_CONNECTION_PER_IP = serverSettings.getInt("MaxConnectionPerIP", 50);
NETWORK_IP_LIST = serverSettings.getString("NetworkList", "");
SESSION_TTL = serverSettings.getLong("SessionTTL", 25000);
MAX_LOGINSESSIONS = serverSettings.getInt("MaxSessions", 200);
}
public static void loadBanFile()
{
File file = new File(BANNED_IP_FILE);
if (!file.exists())
{
// old file position
file = new File(LEGACY_BANNED_IP);
}
if (file.exists() && file.isFile())
{
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
LineNumberReader reader = null;
String line;
String[] parts;
try
{
reader = new LineNumberReader(new InputStreamReader(fis));
while ((line = reader.readLine()) != null)
{
line = line.trim();
// check if this line isnt a comment line
if ((line.length() > 0) && (line.charAt(0) != '#'))
{
// split comments if any
parts = line.split("#", 2);
// discard comments in the line, if any
line = parts[0];
parts = line.split(" ");
final String address = parts[0];
long duration = 0;
if (parts.length > 1)
{
try
{
duration = Long.parseLong(parts[1]);
}
catch (NumberFormatException e)
{
LOGGER.warning("Skipped: Incorrect ban duration (" + parts[1] + ") on (" + file.getName() + "). Line: " + reader.getLineNumber());
continue;
}
}
try
{
LoginController.getInstance().addBanForAddress(address, duration);
}
catch (UnknownHostException e)
{
LOGGER.warning("Skipped: Invalid address (" + parts[0] + ") on (" + file.getName() + "). Line: " + reader.getLineNumber());
}
}
}
}
catch (IOException e)
{
LOGGER.warning("Error while reading the bans file (" + file.getName() + "). Details: " + e);
}
LOGGER.info("Loaded " + LoginController.getInstance().getBannedIps().size() + " IP Bans.");
}
catch (FileNotFoundException e)
{
LOGGER.warning("Failed to load banned IPs file (" + file.getName() + ") for reading. Reason: " + e);
}
finally
{
if (fis != null)
{
try
{
fis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
else
{
LOGGER.info("IP Bans file (" + file.getName() + ") is missing or is a directory, skipped.");
}
}
public static void saveHexid(int serverId, String string)
@@ -3248,6 +3141,11 @@ public class Config
loadFilter();
}
// Hosts and Subnets
final IPConfigData ipcd = new IPConfigData();
GAME_SERVER_SUBNETS = ipcd.getSubnets();
GAME_SERVER_HOSTS = ipcd.getHosts();
loadTelnetConfig();
}
else if (SERVER_MODE == ServerMode.LOGIN)
@@ -3261,4 +3159,155 @@ public class Config
LOGGER.severe("Could not Load Config: server mode was not set.");
}
}
private static class IPConfigData implements IXmlReader
{
private static final List<String> _subnets = new ArrayList<>(5);
private static final List<String> _hosts = new ArrayList<>(5);
public IPConfigData()
{
load();
}
@Override
public void load()
{
final File f = new File(IPCONFIG_FILE);
if (f.exists())
{
LOGGER.info("Network Config: ipconfig.xml exists using manual configuration...");
parseFile(new File(IPCONFIG_FILE));
}
else // Auto configuration...
{
LOGGER.info("Network Config: ipconfig.xml doesn't exists using automatic configuration...");
autoIpConfig();
}
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("gameserver".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("define".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
_subnets.add(attrs.getNamedItem("subnet").getNodeValue());
_hosts.add(attrs.getNamedItem("address").getNodeValue());
if (_hosts.size() != _subnets.size())
{
LOGGER.warning("Failed to Load " + IPCONFIG_FILE + " File - subnets does not match server addresses.");
}
}
}
final Node att = n.getAttributes().getNamedItem("address");
if (att == null)
{
LOGGER.warning("Failed to load " + IPCONFIG_FILE + " file - default server address is missing.");
_hosts.add("127.0.0.1");
}
else
{
_hosts.add(att.getNodeValue());
}
_subnets.add("0.0.0.0/0");
}
}
}
protected void autoIpConfig()
{
String externalIp = "127.0.0.1";
try
{
final URL autoIp = new URL("http://ip1.dynupdate.no-ip.com:8245/");
try (BufferedReader in = new BufferedReader(new InputStreamReader(autoIp.openStream())))
{
externalIp = in.readLine();
}
}
catch (IOException e)
{
LOGGER.log(Level.INFO, "Failed to connect to api.externalip.net please check your internet connection using 127.0.0.1!");
externalIp = "127.0.0.1";
}
try
{
final Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
while (niList.hasMoreElements())
{
final NetworkInterface ni = niList.nextElement();
if (!ni.isUp() || ni.isVirtual())
{
continue;
}
if (!ni.isLoopback() && ((ni.getHardwareAddress() == null) || (ni.getHardwareAddress().length != 6)))
{
continue;
}
for (InterfaceAddress ia : ni.getInterfaceAddresses())
{
if (ia.getAddress() instanceof Inet6Address)
{
continue;
}
final String hostAddress = ia.getAddress().getHostAddress();
final int subnetPrefixLength = ia.getNetworkPrefixLength();
final int subnetMaskInt = IntStream.rangeClosed(1, subnetPrefixLength).reduce((r, e) -> (r << 1) + 1).orElse(0) << (32 - subnetPrefixLength);
final int hostAddressInt = Arrays.stream(hostAddress.split("\\.")).mapToInt(Integer::parseInt).reduce((r, e) -> (r << 8) + e).orElse(0);
final int subnetAddressInt = hostAddressInt & subnetMaskInt;
final String subnetAddress = ((subnetAddressInt >> 24) & 0xFF) + "." + ((subnetAddressInt >> 16) & 0xFF) + "." + ((subnetAddressInt >> 8) & 0xFF) + "." + (subnetAddressInt & 0xFF);
final String subnet = subnetAddress + '/' + subnetPrefixLength;
if (!_subnets.contains(subnet) && !subnet.equals("0.0.0.0/0"))
{
_subnets.add(subnet);
_hosts.add(hostAddress);
LOGGER.info("Network Config: Adding new subnet: " + subnet + " address: " + hostAddress);
}
}
}
// External host and subnet
_hosts.add(externalIp);
_subnets.add("0.0.0.0/0");
LOGGER.info("Network Config: Adding new subnet: 0.0.0.0/0 address: " + externalIp);
}
catch (SocketException e)
{
LOGGER.log(Level.INFO, "Network Config: Configuration failed please configure manually using ipconfig.xml", e);
System.exit(0);
}
}
protected List<String> getSubnets()
{
if (_subnets.isEmpty())
{
return Arrays.asList("0.0.0.0/0");
}
return _subnets;
}
protected List<String> getHosts()
{
if (_hosts.isEmpty())
{
return Arrays.asList("127.0.0.1");
}
return _hosts;
}
}
}

View File

@@ -1,91 +0,0 @@
/*
* 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 org.l2jmobius.commons.crypt;
import java.io.IOException;
import org.l2jmobius.commons.util.Rnd;
/**
* @author KenM
*/
public class LoginCrypt
{
private static final byte[] STATIC_BLOWFISH_KEY =
{
(byte) 0x6b,
(byte) 0x60,
(byte) 0xcb,
(byte) 0x5b,
(byte) 0x82,
(byte) 0xce,
(byte) 0x90,
(byte) 0xb1,
(byte) 0xcc,
(byte) 0x2b,
(byte) 0x6c,
(byte) 0x55,
(byte) 0x6c,
(byte) 0x6c,
(byte) 0x6c,
(byte) 0x6c
};
private final NewCrypt _staticCrypt = new NewCrypt(STATIC_BLOWFISH_KEY);
private NewCrypt _crypt;
private boolean _static = true;
public void setKey(byte[] key)
{
_crypt = new NewCrypt(key);
}
public boolean decrypt(byte[] raw, int offset, int size) throws IOException
{
_crypt.decrypt(raw, offset, size);
return NewCrypt.verifyChecksum(raw, offset, size);
}
public int encrypt(byte[] raw, int offset, int size) throws IOException
{
int newSize = size;
// reserve checksum
newSize += 4;
if (_static)
{
// reserve for XOR "key"
newSize += 4;
// padding
newSize += 8 - (newSize % 8);
NewCrypt.encXORPass(raw, offset, newSize, Rnd.nextInt());
_staticCrypt.crypt(raw, offset, newSize);
_static = false;
}
else
{
// padding
newSize += 8 - (newSize % 8);
NewCrypt.appendChecksum(raw, offset, newSize);
_crypt.crypt(raw, offset, newSize);
}
return newSize;
}
}

View File

@@ -1,46 +0,0 @@
/*
* 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 org.l2jmobius.commons.mmocore;
import java.nio.ByteBuffer;
/**
* @author KenM
* @param <T>
*/
public abstract class MMOClient<T extends MMOConnection<?>>
{
private final T _con;
public MMOClient(T con)
{
_con = con;
}
public T getConnection()
{
return _con;
}
public abstract boolean decrypt(ByteBuffer buf, int size);
public abstract boolean encrypt(ByteBuffer buf, int size);
protected abstract void onDisconnection();
protected abstract void onForcedDisconnection();
}

View File

@@ -1,270 +0,0 @@
/*
* 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 org.l2jmobius.commons.mmocore;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.WritableByteChannel;
/**
* @author KenM
* @param <T>
*/
public class MMOConnection<T extends MMOClient<?>>
{
private final SelectorThread<T> _selectorThread;
private final Socket _socket;
private final InetAddress _address;
private final ReadableByteChannel _readableByteChannel;
private final WritableByteChannel _writableByteChannel;
private final int _port;
private final NioNetStackList<SendablePacket<T>> _sendQueue;
private final SelectionKey _selectionKey;
private ByteBuffer _readBuffer;
private ByteBuffer _primaryWriteBuffer;
private ByteBuffer _secondaryWriteBuffer;
private volatile boolean _pendingClose;
private T _client;
public MMOConnection(SelectorThread<T> selectorThread, Socket socket, SelectionKey key)
{
_selectorThread = selectorThread;
_socket = socket;
_address = socket.getInetAddress();
_readableByteChannel = socket.getChannel();
_writableByteChannel = socket.getChannel();
_port = socket.getPort();
_selectionKey = key;
_sendQueue = new NioNetStackList<>();
}
final void setClient(T client)
{
_client = client;
}
public T getClient()
{
return _client;
}
public void sendPacket(SendablePacket<T> sp)
{
sp._client = _client;
if (_pendingClose)
{
return;
}
synchronized (getSendQueue())
{
_sendQueue.addLast(sp);
}
if (!_sendQueue.isEmpty())
{
try
{
_selectionKey.interestOps(_selectionKey.interestOps() | SelectionKey.OP_WRITE);
}
catch (CancelledKeyException e)
{
// ignore
}
}
}
final SelectionKey getSelectionKey()
{
return _selectionKey;
}
public InetAddress getInetAddress()
{
return _address;
}
public int getPort()
{
return _port;
}
final void close() throws IOException
{
_socket.close();
}
final int read(ByteBuffer buf) throws IOException
{
return _readableByteChannel.read(buf);
}
final int write(ByteBuffer buf) throws IOException
{
return _writableByteChannel.write(buf);
}
final void createWriteBuffer(ByteBuffer buf)
{
if (_primaryWriteBuffer == null)
{
_primaryWriteBuffer = _selectorThread.getPooledBuffer();
_primaryWriteBuffer.put(buf);
}
else
{
final ByteBuffer temp = _selectorThread.getPooledBuffer();
temp.put(buf);
final int remaining = temp.remaining();
_primaryWriteBuffer.flip();
final int limit = _primaryWriteBuffer.limit();
if (remaining >= _primaryWriteBuffer.remaining())
{
temp.put(_primaryWriteBuffer);
_selectorThread.recycleBuffer(_primaryWriteBuffer);
_primaryWriteBuffer = temp;
}
else
{
_primaryWriteBuffer.limit(remaining);
temp.put(_primaryWriteBuffer);
_primaryWriteBuffer.limit(limit);
_primaryWriteBuffer.compact();
_secondaryWriteBuffer = _primaryWriteBuffer;
}
_primaryWriteBuffer = temp;
}
}
final boolean hasPendingWriteBuffer()
{
return _primaryWriteBuffer != null;
}
final void movePendingWriteBufferTo(ByteBuffer dest)
{
_primaryWriteBuffer.flip();
dest.put(_primaryWriteBuffer);
_selectorThread.recycleBuffer(_primaryWriteBuffer);
_primaryWriteBuffer = _secondaryWriteBuffer;
_secondaryWriteBuffer = null;
}
final void setReadBuffer(ByteBuffer buf)
{
_readBuffer = buf;
}
final ByteBuffer getReadBuffer()
{
return _readBuffer;
}
public boolean isClosed()
{
return _pendingClose;
}
final NioNetStackList<SendablePacket<T>> getSendQueue()
{
return _sendQueue;
}
/*
* final SendablePacket<T> getClosePacket() { return _closePacket; }
*/
@SuppressWarnings("unchecked")
public void close(SendablePacket<T> sp)
{
close(new SendablePacket[]
{
sp
});
}
public void close(SendablePacket<T>[] closeList)
{
if (_pendingClose)
{
return;
}
synchronized (getSendQueue())
{
if (!_pendingClose)
{
_pendingClose = true;
_sendQueue.clear();
for (SendablePacket<T> sp : closeList)
{
_sendQueue.addLast(sp);
}
}
}
try
{
_selectionKey.interestOps(_selectionKey.interestOps() & ~SelectionKey.OP_WRITE);
}
catch (CancelledKeyException e)
{
// ignore
}
// _closePacket = sp;
_selectorThread.closeConnection(this);
}
final void releaseBuffers()
{
if (_primaryWriteBuffer != null)
{
_selectorThread.recycleBuffer(_primaryWriteBuffer);
_primaryWriteBuffer = null;
if (_secondaryWriteBuffer != null)
{
_selectorThread.recycleBuffer(_secondaryWriteBuffer);
_secondaryWriteBuffer = null;
}
}
if (_readBuffer != null)
{
_selectorThread.recycleBuffer(_readBuffer);
_readBuffer = null;
}
}
}

View File

@@ -1,101 +0,0 @@
/*
* 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 org.l2jmobius.commons.mmocore;
/**
* @author Forsaiken
* @param <E>
*/
public class NioNetStackList<E>
{
private final NioNetStackNode _start = new NioNetStackNode();
private final NioNetStackNodeBuf _buf = new NioNetStackNodeBuf();
private NioNetStackNode _end = new NioNetStackNode();
public NioNetStackList()
{
clear();
}
public void addLast(E elem)
{
final NioNetStackNode newEndNode = _buf.removeFirst();
_end._value = elem;
_end._next = newEndNode;
_end = newEndNode;
}
public E removeFirst()
{
final NioNetStackNode old = _start._next;
final E value = old._value;
_start._next = old._next;
_buf.addLast(old);
return value;
}
public boolean isEmpty()
{
return _start._next == _end;
}
public void clear()
{
_start._next = _end;
}
protected final class NioNetStackNode
{
protected NioNetStackNode _next;
protected E _value;
}
private final class NioNetStackNodeBuf
{
private final NioNetStackNode _start = new NioNetStackNode();
private NioNetStackNode _end = new NioNetStackNode();
NioNetStackNodeBuf()
{
_start._next = _end;
}
final void addLast(NioNetStackNode node)
{
node._next = null;
node._value = null;
_end._next = node;
_end = node;
}
final NioNetStackNode removeFirst()
{
if (_start._next == _end)
{
return new NioNetStackNode();
}
final NioNetStackNode old = _start._next;
_start._next = old._next;
return old;
}
}
}

View File

@@ -1,139 +0,0 @@
/*
* 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 org.l2jmobius.commons.mmocore;
import java.nio.ByteBuffer;
/**
* @author KenM
* @param <T>
*/
public abstract class ReceivablePacket<T extends MMOClient<?>>extends AbstractPacket<T> implements Runnable
{
NioNetStringBuffer _sbuf;
protected ReceivablePacket()
{
}
protected abstract boolean read();
@Override
public abstract void run();
/**
* Reads <b>byte[]</b> from the buffer.<br>
* Reads as many bytes as the length of the array.
* @param dst : the byte array which will be filled with the data.
*/
protected final void readB(byte[] dst)
{
_buf.get(dst);
}
/**
* Reads <b>byte[]</b> from the buffer.<br>
* Reads as many bytes as the given length (len). Starts to fill the byte array from the given offset to <b>offset</b> + <b>len</b>.
* @param dst : the byte array which will be filled with the data.
* @param offset : starts to fill the byte array from the given offset.
* @param len : the given length of bytes to be read.
*/
protected final void readB(byte[] dst, int offset, int len)
{
_buf.get(dst, offset, len);
}
/**
* Reads <b>byte</b> from the buffer.<br>
* 8bit integer (00)
* @return
*/
protected final int readC()
{
return _buf.get() & 0xFF;
}
/**
* Reads <b>short</b> from the buffer.<br>
* 16bit integer (00 00)
* @return
*/
protected final int readH()
{
return _buf.getShort() & 0xFFFF;
}
/**
* Reads <b>int</b> from the buffer.<br>
* 32bit integer (00 00 00 00)
* @return
*/
protected final int readD()
{
return _buf.getInt();
}
/**
* Reads <b>long</b> from the buffer.<br>
* 64bit integer (00 00 00 00 00 00 00 00)
* @return
*/
protected final long readQ()
{
return _buf.getLong();
}
/**
* Reads <b>double</b> from the buffer.<br>
* 64bit double precision float (00 00 00 00 00 00 00 00)
* @return
*/
protected final double readF()
{
return _buf.getDouble();
}
/**
* Reads <b>String</b> from the buffer.
* @return
*/
protected final String readS()
{
_sbuf.clear();
char ch;
while ((ch = _buf.getChar()) != 0)
{
_sbuf.append(ch);
}
return _sbuf.toString();
}
/**
* packet forge purpose
* @param data
* @param client
* @param sBuffer
*/
public void setBuffers(ByteBuffer data, T client, NioNetStringBuffer sBuffer)
{
_buf = data;
_client = client;
_sbuf = sBuffer;
}
}

View File

@@ -1,52 +0,0 @@
/*
* 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 org.l2jmobius.commons.mmocore;
/**
* @author KenM
*/
public class SelectorConfig
{
public int READ_BUFFER_SIZE = 64 * 1024;
public int WRITE_BUFFER_SIZE = 64 * 1024;
public int HELPER_BUFFER_COUNT = 20;
public int HELPER_BUFFER_SIZE = 64 * 1024;
/**
* Server will try to send MAX_SEND_PER_PASS packets per socket write call<br>
* however it may send less if the write buffer was filled before achieving this value.
*/
public int MAX_SEND_PER_PASS = 10;
/**
* Server will try to read MAX_READ_PER_PASS packets per socket read call<br>
* however it may read less if the read buffer was empty before achieving this value.
*/
public int MAX_READ_PER_PASS = 10;
/**
* Defines how much time (in milis) should the selector sleep, an higher value increases throughput but also increases latency(to a max of the sleep value itself).<br>
* Also an extremely high value(usually > 100) will decrease throughput due to the server not doing enough sends per second (depends on max sends per pass).<br>
* Recommended values:<br>
* 1 for minimal latency.<br>
* 10-30 for an latency/troughput trade-off based on your needs.
*/
public int SLEEP_TIME = 10;
}

View File

@@ -1,692 +0,0 @@
/*
* 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 org.l2jmobius.commons.mmocore;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;
/**
* Parts of design based on network core from WoodenGil
* @param <T>
* @author KenM
*/
public class SelectorThread<T extends MMOClient<?>>extends Thread
{
// default BYTE_ORDER
private static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
// default HEADER_SIZE
private static final int HEADER_SIZE = 2;
// Selector
private final Selector _selector;
// Implementations
private final IPacketHandler<T> _packetHandler;
private final IMMOExecutor<T> _executor;
private final IClientFactory<T> _clientFactory;
// Configurations
private final int HELPER_BUFFER_SIZE;
private final int HELPER_BUFFER_COUNT;
private final int MAX_SEND_PER_PASS;
private final int MAX_READ_PER_PASS;
private final long SLEEP_TIME;
// Main Buffers
private final ByteBuffer DIRECT_WRITE_BUFFER;
private final ByteBuffer WRITE_BUFFER;
private final ByteBuffer READ_BUFFER;
// String Buffer
private final NioNetStringBuffer STRING_BUFFER;
// ByteBuffers General Purpose Pool
private final LinkedList<ByteBuffer> _bufferPool;
// Pending Close
private final NioNetStackList<MMOConnection<T>> _pendingClose;
private boolean _shutdown;
public SelectorThread(SelectorConfig sc, IMMOExecutor<T> executor, IPacketHandler<T> packetHandler, IClientFactory<T> clientFactory) throws IOException
{
super.setName("SelectorThread-" + super.getId());
HELPER_BUFFER_SIZE = sc.HELPER_BUFFER_SIZE;
HELPER_BUFFER_COUNT = sc.HELPER_BUFFER_COUNT;
MAX_SEND_PER_PASS = sc.MAX_SEND_PER_PASS;
MAX_READ_PER_PASS = sc.MAX_READ_PER_PASS;
SLEEP_TIME = sc.SLEEP_TIME;
DIRECT_WRITE_BUFFER = ByteBuffer.allocateDirect(sc.WRITE_BUFFER_SIZE).order(BYTE_ORDER);
WRITE_BUFFER = ByteBuffer.wrap(new byte[sc.WRITE_BUFFER_SIZE]).order(BYTE_ORDER);
READ_BUFFER = ByteBuffer.wrap(new byte[sc.READ_BUFFER_SIZE]).order(BYTE_ORDER);
STRING_BUFFER = new NioNetStringBuffer(64 * 1024);
_pendingClose = new NioNetStackList<>();
_bufferPool = new LinkedList<>();
for (int i = 0; i < HELPER_BUFFER_COUNT; i++)
{
_bufferPool.addLast(ByteBuffer.wrap(new byte[HELPER_BUFFER_SIZE]).order(BYTE_ORDER));
}
_packetHandler = packetHandler;
_clientFactory = clientFactory;
_executor = executor;
_selector = Selector.open();
}
public void openServerSocket(InetAddress address, int tcpPort) throws IOException
{
final ServerSocketChannel selectable = ServerSocketChannel.open();
selectable.configureBlocking(false);
final ServerSocket ss = selectable.socket();
if (address != null)
{
ss.bind(new InetSocketAddress(address, tcpPort));
}
else
{
ss.bind(new InetSocketAddress(tcpPort));
}
selectable.register(_selector, SelectionKey.OP_ACCEPT);
}
protected ByteBuffer getPooledBuffer()
{
if (_bufferPool.isEmpty())
{
return ByteBuffer.wrap(new byte[HELPER_BUFFER_SIZE]).order(BYTE_ORDER);
}
return _bufferPool.removeFirst();
}
protected void recycleBuffer(ByteBuffer buf)
{
if (_bufferPool.size() < HELPER_BUFFER_COUNT)
{
buf.clear();
_bufferPool.addLast(buf);
}
}
@SuppressWarnings("unchecked")
@Override
public void run()
{
int selectedKeysCount = 0;
SelectionKey key;
MMOConnection<T> con;
Iterator<SelectionKey> selectedKeys;
while (!_shutdown)
{
try
{
selectedKeysCount = _selector.selectNow();
}
catch (IOException e)
{
e.printStackTrace();
}
if (selectedKeysCount > 0)
{
selectedKeys = _selector.selectedKeys().iterator();
while (selectedKeys.hasNext())
{
key = selectedKeys.next();
selectedKeys.remove();
con = (MMOConnection<T>) key.attachment();
switch (key.readyOps())
{
case SelectionKey.OP_CONNECT:
{
finishConnection(key, con);
break;
}
case SelectionKey.OP_ACCEPT:
{
acceptConnection(key, con);
break;
}
case SelectionKey.OP_READ:
{
readPacket(key, con);
break;
}
case SelectionKey.OP_WRITE:
{
writePacket(key, con);
break;
}
case SelectionKey.OP_READ | SelectionKey.OP_WRITE:
{
writePacket(key, con);
if (key.isValid())
{
readPacket(key, con);
}
break;
}
}
}
}
synchronized (_pendingClose)
{
while (!_pendingClose.isEmpty())
{
con = _pendingClose.removeFirst();
writeClosePacket(con);
closeConnectionImpl(con.getSelectionKey(), con);
}
}
try
{
Thread.sleep(SLEEP_TIME);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
closeSelectorThread();
}
private final void finishConnection(SelectionKey key, MMOConnection<T> con)
{
try
{
((SocketChannel) key.channel()).finishConnect();
}
catch (IOException e)
{
con.getClient().onForcedDisconnection();
closeConnectionImpl(key, con);
}
// key might have been invalidated on finishConnect()
if (key.isValid())
{
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
key.interestOps(key.interestOps() & ~SelectionKey.OP_CONNECT);
}
}
@SuppressWarnings("all")
private void acceptConnection(SelectionKey key, MMOConnection<T> con)
{
final ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = null;
try
{
while ((sc = ssc.accept()) != null)
{
sc.configureBlocking(false);
final SelectionKey clientKey = sc.register(_selector, SelectionKey.OP_READ);
con = new MMOConnection<>(this, sc.socket(), clientKey);
con.setClient(_clientFactory.create(con));
clientKey.attach(con);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void readPacket(SelectionKey key, MMOConnection<T> con)
{
if (con.isClosed())
{
return;
}
ByteBuffer buf = con.getReadBuffer();
if (buf == null)
{
buf = READ_BUFFER;
}
// if we try to to do a read with no space in the buffer it will read 0 bytes going into infinite loop
if (buf.position() == buf.limit())
{
System.exit(0);
}
int result = -2;
try
{
result = con.read(buf);
}
catch (IOException e)
{
// error handling goes bellow
}
if (result > 0)
{
buf.flip();
final T client = con.getClient();
for (int i = 0; i < MAX_READ_PER_PASS; i++)
{
if (!tryReadPacket(key, client, buf, con))
{
return;
}
}
// only reachable if MAX_READ_PER_PASS has been reached
// check if there are some more bytes in buffer
// and allocate/compact to prevent content lose.
if (buf.remaining() > 0)
{
// did we use the READ_BUFFER ?
if (buf == READ_BUFFER)
{
// move the pending byte to the connections READ_BUFFER
allocateReadBuffer(con);
}
else
{
// move the first byte to the beginning :)
buf.compact();
}
}
}
else
{
switch (result)
{
case 0:
case -1:
{
closeConnectionImpl(key, con);
break;
}
case -2:
{
con.getClient().onForcedDisconnection();
closeConnectionImpl(key, con);
break;
}
}
}
}
private boolean tryReadPacket(SelectionKey key, T client, ByteBuffer buf, MMOConnection<T> con)
{
switch (buf.remaining())
{
case 0:
{
// buffer is full nothing to read
return false;
}
case 1:
{
// we don't have enough data for header so we need to read
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
// did we use the READ_BUFFER ?
if (buf == READ_BUFFER)
{
// move the pending byte to the connections READ_BUFFER
allocateReadBuffer(con);
}
else
{
// move the first byte to the beginning :)
buf.compact();
}
return false;
}
default:
{
// data size excluding header size :>
final int dataPending = (buf.getShort() & 0xFFFF) - HEADER_SIZE;
// do we got enough bytes for the packet?
if (dataPending <= buf.remaining())
{
// avoid parsing dummy packets (packets without body)
if (dataPending > 0)
{
final int pos = buf.position();
parseClientPacket(pos, buf, dataPending, client);
buf.position(pos + dataPending);
}
// if we are done with this buffer
if (!buf.hasRemaining())
{
if (buf != READ_BUFFER)
{
con.setReadBuffer(null);
recycleBuffer(buf);
}
else
{
READ_BUFFER.clear();
}
return false;
}
return true;
}
// we don't have enough bytes for the dataPacket so we need to read
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
// did we use the READ_BUFFER ?
if (buf == READ_BUFFER)
{
// move it's position
buf.position(buf.position() - HEADER_SIZE);
// move the pending byte to the connections READ_BUFFER
allocateReadBuffer(con);
}
else
{
buf.position(buf.position() - HEADER_SIZE);
buf.compact();
}
return false;
}
}
}
private void allocateReadBuffer(MMOConnection<T> con)
{
con.setReadBuffer(getPooledBuffer().put(READ_BUFFER));
READ_BUFFER.clear();
}
private final void parseClientPacket(int pos, ByteBuffer buf, int dataSize, T client)
{
final boolean ret = client.decrypt(buf, dataSize);
if (ret && buf.hasRemaining())
{
// apply limit
final int limit = buf.limit();
buf.limit(pos + dataSize);
final ReceivablePacket<T> cp = _packetHandler.handlePacket(buf, client);
if (cp != null)
{
cp._buf = buf;
cp._sbuf = STRING_BUFFER;
cp._client = client;
if (cp.read())
{
_executor.execute(cp);
}
cp._buf = null;
cp._sbuf = null;
}
buf.limit(limit);
}
}
private void writeClosePacket(MMOConnection<T> con)
{
SendablePacket<T> sp;
synchronized (con.getSendQueue())
{
if (con.getSendQueue().isEmpty())
{
return;
}
while ((sp = con.getSendQueue().removeFirst()) != null)
{
WRITE_BUFFER.clear();
putPacketIntoWriteBuffer(con.getClient(), sp);
WRITE_BUFFER.flip();
try
{
con.write(WRITE_BUFFER);
}
catch (IOException e)
{
// error handling goes on the if bellow
}
}
}
}
protected void writePacket(SelectionKey key, MMOConnection<T> con)
{
if (!prepareWriteBuffer(con))
{
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
return;
}
DIRECT_WRITE_BUFFER.flip();
final int size = DIRECT_WRITE_BUFFER.remaining();
int result = -1;
try
{
result = con.write(DIRECT_WRITE_BUFFER);
}
catch (IOException e)
{
// error handling goes on the if bellow
}
// check if no error happened
if (result >= 0)
{
// check if we written everything
if (result == size)
{
// complete write
synchronized (con.getSendQueue())
{
if (con.getSendQueue().isEmpty() && !con.hasPendingWriteBuffer())
{
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
}
}
}
else
{
// incomplete write
con.createWriteBuffer(DIRECT_WRITE_BUFFER);
}
}
else
{
con.getClient().onForcedDisconnection();
closeConnectionImpl(key, con);
}
}
private boolean prepareWriteBuffer(MMOConnection<T> con)
{
boolean hasPending = false;
DIRECT_WRITE_BUFFER.clear();
// if there is pending content add it
if (con.hasPendingWriteBuffer())
{
con.movePendingWriteBufferTo(DIRECT_WRITE_BUFFER);
hasPending = true;
}
if ((DIRECT_WRITE_BUFFER.remaining() > 1) && !con.hasPendingWriteBuffer())
{
final NioNetStackList<SendablePacket<T>> sendQueue = con.getSendQueue();
final T client = con.getClient();
SendablePacket<T> sp;
for (int i = 0; i < MAX_SEND_PER_PASS; i++)
{
synchronized (con.getSendQueue())
{
if (sendQueue.isEmpty())
{
sp = null;
}
else
{
sp = sendQueue.removeFirst();
}
}
if (sp == null)
{
break;
}
hasPending = true;
// put into WriteBuffer
putPacketIntoWriteBuffer(client, sp);
WRITE_BUFFER.flip();
if (DIRECT_WRITE_BUFFER.remaining() < WRITE_BUFFER.limit())
{
con.createWriteBuffer(WRITE_BUFFER);
break;
}
DIRECT_WRITE_BUFFER.put(WRITE_BUFFER);
}
}
return hasPending;
}
private void putPacketIntoWriteBuffer(T client, SendablePacket<T> sp)
{
WRITE_BUFFER.clear();
// reserve space for the size
final int headerPos = WRITE_BUFFER.position();
final int dataPos = headerPos + HEADER_SIZE;
WRITE_BUFFER.position(dataPos);
// set the write buffer
sp._buf = WRITE_BUFFER;
// write content to buffer
sp.write();
// delete the write buffer
sp._buf = null;
// size (inclusive header)
int dataSize = WRITE_BUFFER.position() - dataPos;
WRITE_BUFFER.position(dataPos);
client.encrypt(WRITE_BUFFER, dataSize);
// recalculate size after encryption
dataSize = WRITE_BUFFER.position() - dataPos;
WRITE_BUFFER.position(headerPos);
// write header
WRITE_BUFFER.putShort((short) (dataSize + HEADER_SIZE));
WRITE_BUFFER.position(dataPos + dataSize);
}
protected void closeConnection(MMOConnection<T> con)
{
synchronized (_pendingClose)
{
_pendingClose.addLast(con);
}
}
private void closeConnectionImpl(SelectionKey key, MMOConnection<T> con)
{
try
{
// notify connection
con.getClient().onDisconnection();
}
finally
{
try
{
// close socket and the SocketChannel
con.close();
}
catch (IOException e)
{
// ignore, we are closing anyway
}
finally
{
con.releaseBuffers();
// clear attachment
key.attach(null);
// cancel key
key.cancel();
}
}
}
public void shutdown()
{
_shutdown = true;
}
protected void closeSelectorThread()
{
for (SelectionKey key : _selector.keys())
{
try
{
key.channel().close();
}
catch (IOException e)
{
// ignore
}
}
try
{
_selector.close();
}
catch (IOException e)
{
// Ignore
}
}
}

View File

@@ -1,119 +0,0 @@
/*
* 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 org.l2jmobius.commons.mmocore;
/**
* @author KenM
* @param <T>
*/
public abstract class SendablePacket<T extends MMOClient<?>>extends AbstractPacket<T>
{
protected final void putInt(int value)
{
_buf.putInt(value);
}
protected final void putDouble(double value)
{
_buf.putDouble(value);
}
protected final void putFloat(float value)
{
_buf.putFloat(value);
}
/**
* Write <b>byte</b> to the buffer.<br>
* 8bit integer (00)
* @param data
*/
protected final void writeC(int data)
{
_buf.put((byte) data);
}
/**
* Write <b>double</b> to the buffer.<br>
* 64bit double precision float (00 00 00 00 00 00 00 00)
* @param value
*/
protected final void writeF(double value)
{
_buf.putDouble(value);
}
/**
* Write <b>short</b> to the buffer.<br>
* 16bit integer (00 00)
* @param value
*/
protected final void writeH(int value)
{
_buf.putShort((short) value);
}
/**
* Write <b>int</b> to the buffer.<br>
* 32bit integer (00 00 00 00)
* @param value
*/
protected final void writeD(int value)
{
_buf.putInt(value);
}
/**
* Write <b>long</b> to the buffer.<br>
* 64bit integer (00 00 00 00 00 00 00 00)
* @param value
*/
protected final void writeQ(long value)
{
_buf.putLong(value);
}
/**
* Write <b>byte[]</b> to the buffer.<br>
* 8bit integer array (00 ...)
* @param data
*/
protected final void writeB(byte[] data)
{
_buf.put(data);
}
/**
* Write <b>String</b> to the buffer.
* @param text
*/
protected final void writeS(String text)
{
if (text != null)
{
final int len = text.length();
for (int i = 0; i < len; i++)
{
_buf.putChar(text.charAt(i));
}
}
_buf.putChar('\000');
}
protected abstract void write();
}

View File

@@ -14,17 +14,22 @@
* 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 org.l2jmobius.loginserver.network.clientpackets;
package org.l2jmobius.commons.network;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;
/**
* @version $Revision: 1.2.4.1 $ $Date: 2005/03/27 15:30:12 $
*/
public abstract class ClientBasePacket
public abstract class BaseRecievePacket
{
private static final Logger LOGGER = Logger.getLogger(BaseRecievePacket.class.getName());
private final byte[] _decrypt;
private int _off;
public ClientBasePacket(byte[] decrypt)
public BaseRecievePacket(byte[] decrypt)
{
_decrypt = decrypt;
_off = 1; // skip packet type id
@@ -41,27 +46,24 @@ public abstract class ClientBasePacket
public int readC()
{
final int result = _decrypt[_off++] & 0xff;
return result;
return _decrypt[_off++] & 0xff;
}
public int readH()
{
int result = _decrypt[_off++] & 0xff;
result |= (_decrypt[_off++] << 8) & 0xff00;
return result;
return (_decrypt[_off++] & 0xff) | ((_decrypt[_off++] << 8) & 0xff00);
}
public double readF()
{
long result = _decrypt[_off++] & 0xff;
result |= (_decrypt[_off++] << 8) & 0xff00;
result |= (_decrypt[_off++] << 0x10) & 0xff0000;
result |= (_decrypt[_off++] << 0x18) & 0xff000000;
result |= (_decrypt[_off++] << 0x20) & 0xff00000000L;
result |= (_decrypt[_off++] << 0x28) & 0xff0000000000L;
result |= (_decrypt[_off++] << 0x30) & 0xff000000000000L;
result |= (_decrypt[_off++] << 0x38) & 0xff00000000000000L;
result |= (_decrypt[_off++] & 0xffL) << 8L;
result |= (_decrypt[_off++] & 0xffL) << 16L;
result |= (_decrypt[_off++] & 0xffL) << 24L;
result |= (_decrypt[_off++] & 0xffL) << 32L;
result |= (_decrypt[_off++] & 0xffL) << 40L;
result |= (_decrypt[_off++] & 0xffL) << 48L;
result |= (_decrypt[_off++] & 0xffL) << 56L;
return Double.longBitsToDouble(result);
}
@@ -70,13 +72,13 @@ public abstract class ClientBasePacket
String result = null;
try
{
result = new String(_decrypt, _off, _decrypt.length - _off, "UTF-16LE");
result = new String(_decrypt, _off, _decrypt.length - _off, StandardCharsets.UTF_16LE);
result = result.substring(0, result.indexOf(0x00));
_off += (result.length() * 2) + 2;
}
catch (Exception e)
{
e.printStackTrace();
LOGGER.warning(getClass().getSimpleName() + ": " + e.getMessage());
}
return result;
}
@@ -84,11 +86,21 @@ public abstract class ClientBasePacket
public byte[] readB(int length)
{
final byte[] result = new byte[length];
for (int i = 0; i < length; i++)
{
result[i] = _decrypt[_off + i];
}
System.arraycopy(_decrypt, _off, result, 0, length);
_off += length;
return result;
}
public long readQ()
{
long result = _decrypt[_off++] & 0xff;
result |= (_decrypt[_off++] & 0xffL) << 8L;
result |= (_decrypt[_off++] & 0xffL) << 16L;
result |= (_decrypt[_off++] & 0xffL) << 24L;
result |= (_decrypt[_off++] & 0xffL) << 32L;
result |= (_decrypt[_off++] & 0xffL) << 40L;
result |= (_decrypt[_off++] & 0xffL) << 48L;
result |= (_decrypt[_off++] & 0xffL) << 56L;
return result;
}
}

View File

@@ -14,20 +14,23 @@
* 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 org.l2jmobius.loginserver.network.serverpackets;
package org.l2jmobius.commons.network;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;
/**
* @version $Revision: 1.2.4.1 $ $Date: 2005/03/27 15:30:11 $
*/
public abstract class ServerBasePacket
public abstract class BaseSendablePacket
{
ByteArrayOutputStream _bao;
private static final Logger LOGGER = Logger.getLogger(BaseSendablePacket.class.getName());
protected ServerBasePacket()
private final ByteArrayOutputStream _bao;
protected BaseSendablePacket()
{
_bao = new ByteArrayOutputStream();
}
@@ -75,7 +78,7 @@ public abstract class ServerBasePacket
}
catch (Exception e)
{
e.printStackTrace();
LOGGER.warning(getClass().getSimpleName() + ": " + e.getMessage());
}
_bao.write(0);
@@ -90,10 +93,22 @@ public abstract class ServerBasePacket
}
catch (IOException e)
{
e.printStackTrace();
LOGGER.warning(getClass().getSimpleName() + ": " + e.getMessage());
}
}
protected void writeQ(long value)
{
_bao.write((int) (value & 0xff));
_bao.write((int) ((value >> 8) & 0xff));
_bao.write((int) ((value >> 16) & 0xff));
_bao.write((int) ((value >> 24) & 0xff));
_bao.write((int) ((value >> 32) & 0xff));
_bao.write((int) ((value >> 40) & 0xff));
_bao.write((int) ((value >> 48) & 0xff));
_bao.write((int) ((value >> 56) & 0xff));
}
public int getLength()
{
return _bao.size() + 2;
@@ -102,7 +117,8 @@ public abstract class ServerBasePacket
public byte[] getBytes()
{
// if (this instanceof Init)
// writeD(0x00); //reserve for XOR initial key
// writeD(0x00); // reserve for XOR initial key
writeD(0x00); // reserve for checksum
final int padding = _bao.size() % 8;
@@ -113,6 +129,7 @@ public abstract class ServerBasePacket
writeC(0x00);
}
}
return _bao.toByteArray();
}

View File

@@ -0,0 +1,46 @@
/*
* 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 org.l2jmobius.commons.network;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* @author Nos
* @param <T>
*/
public abstract class ChannelInboundHandler<T extends ChannelInboundHandler<?>>extends SimpleChannelInboundHandler<IIncomingPacket<T>>
{
private Channel _channel;
@Override
public void channelActive(ChannelHandlerContext ctx)
{
_channel = ctx.channel();
}
public void setConnectionState(IConnectionState connectionState)
{
_channel.attr(IConnectionState.ATTRIBUTE_KEY).set(connectionState);
}
public IConnectionState getConnectionState()
{
return _channel != null ? _channel.attr(IConnectionState.ATTRIBUTE_KEY).get() : null;
}
}

View File

@@ -14,18 +14,14 @@
* 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 org.l2jmobius.gameserver.network.serverpackets;
package org.l2jmobius.commons.network;
import io.netty.util.AttributeKey;
/**
* Format: (ch).
* @author -Wooden-
* @author Nos
*/
public class ExOrcMove extends GameServerPacket
public interface IConnectionState
{
@Override
protected void writeImpl()
{
writeC(0xfe);
writeH(0x44);
}
AttributeKey<IConnectionState> ATTRIBUTE_KEY = AttributeKey.valueOf(IConnectionState.class, "");
}

View File

@@ -14,14 +14,16 @@
* 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 org.l2jmobius.commons.mmocore;
package org.l2jmobius.commons.network;
import java.nio.channels.SocketChannel;
import io.netty.buffer.ByteBuf;
/**
* @author KenM
* @author Nos
*/
public interface IAcceptFilter
public interface ICrypt
{
boolean accept(SocketChannel sc);
}
void encrypt(ByteBuf buf);
void decrypt(ByteBuf buf);
}

View File

@@ -14,13 +14,21 @@
* 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 org.l2jmobius.commons.mmocore;
package org.l2jmobius.commons.network;
/**
* @author KenM
* @author Nos
* @param <T>
*/
public interface IClientFactory<T extends MMOClient<?>>
public interface IIncomingPacket<T>
{
T create(MMOConnection<T> con);
}
/**
* Reads a packet.
* @param client the client
* @param packet the packet reader
* @return {@code true} if packet was read successfully, {@code false} otherwise.
*/
boolean read(T client, PacketReader packet);
void run(T client) throws Exception;
}

View File

@@ -14,22 +14,19 @@
* 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 org.l2jmobius.commons.mmocore;
package org.l2jmobius.commons.network;
import java.nio.ByteBuffer;
import java.util.Set;
/**
* @author KenM
* @author Nos
* @param <T>
*/
public abstract class AbstractPacket<T extends MMOClient<?>>
public interface IIncomingPackets<T>extends IConnectionState
{
protected ByteBuffer _buf;
int getPacketId();
T _client;
IIncomingPacket<T> newIncomingPacket();
public T getClient()
{
return _client;
}
}
Set<IConnectionState> getConnectionStates();
}

View File

@@ -14,14 +14,16 @@
* 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 org.l2jmobius.loginserver.network.serverpackets;
import org.l2jmobius.commons.mmocore.SendablePacket;
import org.l2jmobius.loginserver.LoginClient;
package org.l2jmobius.commons.network;
/**
* @author KenM
* @author Nos
*/
public abstract class LoginServerPacket extends SendablePacket<LoginClient>
public interface IOutgoingPacket
{
/**
* @param packet the packet writer
* @return {@code true} if packet was writen successfully, {@code false} otherwise.
*/
boolean write(PacketWriter packet);
}

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 org.l2jmobius.commons.network;
import java.util.logging.Logger;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @author Nos
*/
public class NetworkManager
{
private static final Logger LOGGER = Logger.getLogger(NetworkManager.class.getName());
private final ServerBootstrap _serverBootstrap;
private final String _host;
private final int _port;
private ChannelFuture _channelFuture;
public NetworkManager(EventLoopGroup bossGroup, EventLoopGroup workerGroup, ChannelInitializer<SocketChannel> clientInitializer, String host, int port)
{
// @formatter:off
_serverBootstrap = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(clientInitializer)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
// @formatter:on
_host = host;
_port = port;
}
public ChannelFuture getChannelFuture()
{
return _channelFuture;
}
public void start() throws InterruptedException
{
if ((_channelFuture != null) && !_channelFuture.isDone())
{
return;
}
_channelFuture = _serverBootstrap.bind(_host, _port).sync();
LOGGER.info(getClass().getSimpleName() + ": Listening on " + _host + ":" + _port);
}
public void stop() throws InterruptedException
{
_channelFuture.channel().close().sync();
}
}

View File

@@ -0,0 +1,163 @@
/*
* 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 org.l2jmobius.commons.network;
import io.netty.buffer.ByteBuf;
/**
* @author Nos
*/
public class PacketReader
{
private final ByteBuf _buf;
public PacketReader(ByteBuf buf)
{
_buf = buf;
}
/**
* Gets the readable bytes.
* @return the readable bytes
*/
public int getReadableBytes()
{
return _buf.readableBytes();
}
/**
* Reads an unsigned byte.
* @return the unsigned byte
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code 1}
*/
public short readC()
{
return _buf.readUnsignedByte();
}
/**
* Reads an unsigned short.
* @return the unsigned short
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code 2}
*/
public int readH()
{
return _buf.readUnsignedShortLE();
}
/**
* Reads an integer.
* @return the integer
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code 4}
*/
public int readD()
{
return _buf.readIntLE();
}
/**
* Reads a long.
* @return the long
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code 8}
*/
public long readQ()
{
return _buf.readLongLE();
}
/**
* Reads a float.
* @return the float
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code 4}
*/
public float readE()
{
return Float.intBitsToFloat(_buf.readIntLE());
}
/**
* Reads a double.
* @return the double
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code 8}
*/
public double readF()
{
return Double.longBitsToDouble(_buf.readLongLE());
}
/**
* Reads a string.
* @return the string
* @throws IndexOutOfBoundsException if string {@code null} terminator is not found within {@code readableBytes}
*/
public String readS()
{
final StringBuilder sb = new StringBuilder();
char chr;
while ((chr = Character.reverseBytes(_buf.readChar())) != 0)
{
sb.append(chr);
}
return sb.toString();
}
/**
* Reads a fixed length string.
* @return the string
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code 2 + String.length * 2}
*/
public String readString()
{
final StringBuilder sb = new StringBuilder();
final int stringLength = _buf.readShortLE();
if ((stringLength * 2) > _buf.readableBytes())
{
throw new IndexOutOfBoundsException("readerIndex(" + _buf.readerIndex() + ") + length(" + (stringLength * 2) + ") exceeds writerIndex(" + _buf.writerIndex() + "): " + _buf);
}
for (int i = 0; i < stringLength; i++)
{
sb.append(Character.reverseBytes(_buf.readChar()));
}
return sb.toString();
}
/**
* Reads a byte array.
* @param length the length
* @return the byte array
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code length}
*/
public byte[] readB(int length)
{
final byte[] result = new byte[length];
_buf.readBytes(result);
return result;
}
/**
* Reads a byte array.
* @param dst the destination
* @param dstIndex the destination index to start writing the bytes from
* @param length the length
* @throws IndexOutOfBoundsException if {@code readableBytes} is less than {@code length}, if the specified dstIndex is less than 0 or if {@code dstIndex + length} is greater than {@code dst.length}
*/
public void readB(byte[] dst, int dstIndex, int length)
{
_buf.readBytes(dst, dstIndex, length);
}
}

View File

@@ -0,0 +1,141 @@
/*
* 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 org.l2jmobius.commons.network;
import io.netty.buffer.ByteBuf;
/**
* @author Nos
*/
public class PacketWriter
{
private final ByteBuf _buf;
public PacketWriter(ByteBuf buf)
{
_buf = buf;
}
/**
* Gets the writable bytes.
* @return the writable bytes
*/
public int getWritableBytes()
{
return _buf.writableBytes();
}
/**
* Writes a byte.
* @param value the byte (The 24 high-order bits are ignored)
*/
public void writeC(int value)
{
_buf.writeByte(value);
}
/**
* Writes a short.
* @param value the short (The 16 high-order bits are ignored)
*/
public void writeH(int value)
{
_buf.writeShortLE(value);
}
/**
* Writes an integer.
* @param value the integer
*/
public void writeD(int value)
{
_buf.writeIntLE(value);
}
/**
* Writes a long.
* @param value the long
*/
public void writeQ(long value)
{
_buf.writeLongLE(value);
}
/**
* Writes a float.
* @param value the float
*/
public void writeE(float value)
{
_buf.writeIntLE(Float.floatToIntBits(value));
}
/**
* Writes a double.
* @param value the double
*/
public void writeF(double value)
{
_buf.writeLongLE(Double.doubleToLongBits(value));
}
/**
* Writes a string.
* @param value the string
*/
public void writeS(String value)
{
if (value != null)
{
for (int i = 0; i < value.length(); i++)
{
_buf.writeChar(Character.reverseBytes(value.charAt(i)));
}
}
_buf.writeChar(0);
}
/**
* Writes a string with fixed length specified as [short length, char[length] data].
* @param value the string
*/
public void writeString(String value)
{
if (value != null)
{
_buf.writeShortLE(value.length());
for (int i = 0; i < value.length(); i++)
{
_buf.writeChar(Character.reverseBytes(value.charAt(i)));
}
}
else
{
_buf.writeShort(0);
}
}
/**
* Writes a byte array.
* @param bytes the byte array
*/
public void writeB(byte[] bytes)
{
_buf.writeBytes(bytes);
}
}

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 org.l2jmobius.commons.network.codecs;
import java.util.List;
import org.l2jmobius.commons.network.ICrypt;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
/**
* @author Nos
*/
public class CryptCodec extends ByteToMessageCodec<ByteBuf>
{
private final ICrypt _crypt;
public CryptCodec(ICrypt crypt)
{
super();
_crypt = crypt;
}
/*
* (non-Javadoc)
* @see io.netty.handler.codec.ByteToMessageCodec#encode(io.netty.channel.ChannelHandlerContext, java.lang.Object, io.netty.buffer.ByteBuf)
*/
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out)
{
// Check if there are any data to encrypt.
if (!msg.isReadable())
{
return;
}
msg.resetReaderIndex();
_crypt.encrypt(msg);
msg.resetReaderIndex();
out.writeBytes(msg);
}
/*
* (non-Javadoc)
* @see io.netty.handler.codec.ByteToMessageCodec#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
*/
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
{
in.resetReaderIndex();
_crypt.decrypt(in);
in.readerIndex(in.writerIndex());
out.add(in.copy(0, in.writerIndex()));
}
}

View File

@@ -14,33 +14,28 @@
* 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 org.l2jmobius.loginserver.network.clientpackets;
package org.l2jmobius.commons.network.codecs;
import java.util.logging.Logger;
import java.util.List;
import org.l2jmobius.commons.mmocore.ReceivablePacket;
import org.l2jmobius.loginserver.LoginClient;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
/**
* @author KenM
* @author Nos
*/
public abstract class LoginClientPacket extends ReceivablePacket<LoginClient>
@Sharable
public class LengthFieldBasedFrameEncoder extends MessageToMessageEncoder<ByteBuf>
{
private static final Logger LOGGER = Logger.getLogger(LoginClientPacket.class.getName());
@Override
protected final boolean read()
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)
{
try
{
return readImpl();
}
catch (Exception e)
{
LOGGER.warning("ERROR READING: " + e);
return false;
}
final ByteBuf buf = ctx.alloc().buffer(2);
final short length = (short) (msg.readableBytes() + 2);
buf.writeShortLE(length);
out.add(buf);
out.add(msg.retain());
}
protected abstract boolean readImpl();
}

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 org.l2jmobius.commons.network.codecs;
import java.util.List;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.IConnectionState;
import org.l2jmobius.commons.network.IIncomingPacket;
import org.l2jmobius.commons.network.IIncomingPackets;
import org.l2jmobius.commons.network.PacketReader;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
/**
* @author Nos
* @param <T>
*/
public class PacketDecoder<T>extends ByteToMessageDecoder
{
private static final Logger LOGGER = Logger.getLogger(PacketDecoder.class.getName());
private final IIncomingPackets<T>[] _incomingPackets;
private final T _client;
public PacketDecoder(IIncomingPackets<T>[] incomingPackets, T client)
{
_incomingPackets = incomingPackets;
_client = client;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
{
if ((in == null) || !in.isReadable())
{
return;
}
try
{
final short packetId = in.readUnsignedByte();
if (packetId >= _incomingPackets.length)
{
LOGGER.finer("Unknown packet: " + Integer.toHexString(packetId));
return;
}
final IIncomingPackets<T> incomingPacket = _incomingPackets[packetId];
if (incomingPacket == null)
{
LOGGER.finer("Unknown packet: " + Integer.toHexString(packetId));
return;
}
final IConnectionState connectionState = ctx.channel().attr(IConnectionState.ATTRIBUTE_KEY).get();
if ((connectionState == null) || !incomingPacket.getConnectionStates().contains(connectionState))
{
// LOGGER.warning(incomingPacket + ": Connection at invalid state: " + connectionState + " Required States: " + incomingPacket.getConnectionStates());
return;
}
final IIncomingPacket<T> packet = incomingPacket.newIncomingPacket();
if ((packet != null) && packet.read(_client, new PacketReader(in)))
{
out.add(packet);
}
}
finally
{
// We always consider that we read whole packet.
in.readerIndex(in.writerIndex());
}
}
}

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 org.l2jmobius.commons.network.codecs;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.IOutgoingPacket;
import org.l2jmobius.commons.network.PacketWriter;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
/**
* @author Nos
*/
@Sharable
public class PacketEncoder extends MessageToByteEncoder<IOutgoingPacket>
{
private static final Logger LOGGER = Logger.getLogger(PacketEncoder.class.getName());
private final int _maxPacketSize;
public PacketEncoder(int maxPacketSize)
{
super();
_maxPacketSize = maxPacketSize;
}
@Override
protected void encode(ChannelHandlerContext ctx, IOutgoingPacket packet, ByteBuf out)
{
try
{
if (packet.write(new PacketWriter(out)))
{
if (out.writerIndex() > _maxPacketSize)
{
throw new IllegalStateException("Packet (" + packet + ") size (" + out.writerIndex() + ") is bigger than the expected client limit (" + _maxPacketSize + ")");
}
}
else
{
// Avoid sending the packet
out.clear();
}
}
catch (Throwable e)
{
LOGGER.log(Level.WARNING, "Failed sending Packet(" + packet + ")", e);
// Avoid sending the packet if some exception happened
out.clear();
}
}
}

View File

@@ -1,30 +1,24 @@
/*
* This file is part of the L2J Mobius project.
* This file is based on the Blowfish Engine that is part of the BouncyCastle JCE.
* Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* 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/>.
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.l2jmobius.commons.crypt;
package org.l2jmobius.commons.util.crypt;
import java.io.IOException;
/**
* This file is based on the Blowfish Engine that is part of the BouncyCastle JCE Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
public class BlowfishEngine
{
private static final int[] KP =
@@ -1084,19 +1078,16 @@ public class BlowfishEngine
0x578FDFE3,
0x3AC372E6
};
// ====================================
// Useful constants
// ====================================
private static final int ROUNDS = 16;
private static final int BLOCK_SIZE = 8; // bytes = 64 bits
private static final int SBOX_SK = 256;
private static final int P_SZ = ROUNDS + 2;
private final int[] S0; // the s-boxes
private final int[] S1;
private final int[] S2;
private final int[] S3;
private final int[] S1; // the s-boxes
private final int[] S2; // the s-boxes
private final int[] S3; // the s-boxes
private final int[] P; // the p-array
private boolean encrypting = false;
private byte[] workingKey = null;
public BlowfishEngine()
@@ -1110,13 +1101,10 @@ public class BlowfishEngine
/**
* Initialize a Blowfish cipher.
* @param pEncrypting whether or not we are for encryption.
* @param key the key used to set up the cipher.
* @exception IllegalArgumentException if the params argument is inappropriate.
* @param key the key used to set up the cipher
*/
public void init(boolean pEncrypting, byte[] key)
public void init(byte[] key)
{
encrypting = pEncrypting;
workingKey = key;
setKey(workingKey);
}
@@ -1126,50 +1114,14 @@ public class BlowfishEngine
return "Blowfish";
}
public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws IOException
{
if (workingKey == null)
{
throw new IllegalStateException("Blowfish not initialised");
}
if ((inOff + BLOCK_SIZE) > in.length)
{
throw new IOException("input buffer too short");
}
if ((outOff + BLOCK_SIZE) > out.length)
{
throw new IOException("output buffer too short");
}
if (encrypting)
{
encryptBlock(in, inOff, out, outOff);
}
else
{
decryptBlock(in, inOff, out, outOff);
}
return BLOCK_SIZE;
}
public void reset()
{
}
public int getBlockSize()
{
return BLOCK_SIZE;
}
// ==================================
// Private Implementation
// ==================================
private int func(int x)
{
return ((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff];
return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]);
}
/**
@@ -1185,13 +1137,23 @@ public class BlowfishEngine
for (int s = 0; s < size; s += 2)
{
xl ^= P[0];
for (int i = 1; i < ROUNDS; i += 2)
{
xr ^= func(xl) ^ P[i];
xl ^= func(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
xr ^= func(xl) ^ P[1];
xl ^= func(xr) ^ P[2];
xr ^= func(xl) ^ P[3];
xl ^= func(xr) ^ P[4];
xr ^= func(xl) ^ P[5];
xl ^= func(xr) ^ P[6];
xr ^= func(xl) ^ P[7];
xl ^= func(xr) ^ P[8];
xr ^= func(xl) ^ P[9];
xl ^= func(xr) ^ P[10];
xr ^= func(xl) ^ P[11];
xl ^= func(xr) ^ P[12];
xr ^= func(xl) ^ P[13];
xl ^= func(xr) ^ P[14];
xr ^= func(xl) ^ P[15];
xl ^= func(xr) ^ P[16];
xr ^= P[17];
table[s] = xr;
table[s + 1] = xl;
xr = xl; // end of cycle swap
@@ -1201,16 +1163,19 @@ public class BlowfishEngine
private void setKey(byte[] key)
{
/*
* - comments are from _Applied Crypto_, Schneier, p338 please be careful comparing the two, AC numbers the arrays from 1, the enclosed code from 0. (1) Initialise the S-boxes and the P-array, with a fixed string This string contains the hexadecimal digits of pi (3.141...)
/**
* - comments are from _Applied Crypto_, Schneier, p338.<br>
* Please be careful comparing the two, AC numbers the arrays from 1, the enclosed code from 0.<br>
* (1) Initialize the S-boxes and the P-array, with a fixed string This string contains the hexadecimal digits of pi (3.141...)
*/
System.arraycopy(KS0, 0, S0, 0, SBOX_SK);
System.arraycopy(KS1, 0, S1, 0, SBOX_SK);
System.arraycopy(KS2, 0, S2, 0, SBOX_SK);
System.arraycopy(KS3, 0, S3, 0, SBOX_SK);
System.arraycopy(KP, 0, P, 0, P_SZ);
/*
* (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the second 32-bits of the key, and so on for all bits of the key (up to P[17]). Repeatedly cycle through the key bits until the entire P-array has been XOR-ed with the key bits
/**
* (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the second 32-bits of the key, and so on for all bits of the key (up to P[17]).<br>
* Repeatedly cycle through the key bits until the entire P-array has been XOR-ed with the key bits
*/
final int keyLength = key.length;
int keyIndex = 0;
@@ -1231,9 +1196,12 @@ public class BlowfishEngine
// XOR the newly created 32 bit chunk onto the P-array
P[i] ^= data;
}
/*
* (3) Encrypt the all-zero string with the Blowfish algorithm, using the subkeys described in (1) and (2) (4) Replace P1 and P2 with the output of step (3) (5) Encrypt the output of step(3) using the Blowfish algorithm, with the modified subkeys. (6) Replace P3 and P4 with the output of
* step (5) (7) Continue the process, replacing all elements of the P-array and then all four S-boxes in order, with the output of the continuously changing Blowfish algorithm
/**
* (3) Encrypt the all-zero string with the Blowfish algorithm, using the subkeys described in (1) and (2)<br>
* (4) Replace P1 and P2 with the output of step (3)<br>
* (5) Encrypt the output of step(3) using the Blowfish algorithm, with the modified subkeys.<br>
* (6) Replace P3 and P4 with the output of step (5)<br>
* (7) Continue the process, replacing all elements of the P-array and then all four S-boxes in order, with the output of the continuously changing Blowfish algorithm
*/
processTable(0, 0, P);
processTable(P[P_SZ - 2], P[P_SZ - 1], S0);
@@ -1243,61 +1211,246 @@ public class BlowfishEngine
}
/**
* Encrypt the given input starting at the given offset and place the result in the provided buffer starting at the given offset. The input will be an exact multiple of our blocksize.
* @param src
* @param srcIndex
* @param dst
* @param dstIndex
* Method to encrypt the block at the given index.<br>
* The encrypted block goes directly to the source array at the given index.
* @param src source array with the plain data
* @param srcIndex index where the block to encrypt is located
* @throws IllegalStateException The cipher was not yet initialized
* @throws IOException The source array is too small to hold a block at the given index
*/
private void encryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex)
public void tryEncryptBlock(byte[] src, int srcIndex) throws IOException
{
if (workingKey == null)
{
throw new IllegalStateException("Blowfish not initialized");
}
if ((srcIndex + BLOCK_SIZE) > src.length)
{
throw new IOException("input buffer too short");
}
encryptBlock(src, srcIndex);
}
/**
* Method to encrypt the block at the given index.<br>
* The encrypted block goes to the destination array at the given index.
* @param src source array with the plain data
* @param srcIndex index where the block to encrypt is located
* @param dst destination array the encryption will go to
* @param dstIndex index where the encrypted block is to be stored
* @throws IllegalStateException The cipher was not yet initialized
* @throws IOException The source or destination array is too small to hold a block at the given index
*/
public void tryEncryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) throws IOException
{
if (workingKey == null)
{
throw new IllegalStateException("Blowfish not initialized");
}
if ((srcIndex + BLOCK_SIZE) > src.length)
{
throw new IOException("input buffer too short");
}
if ((dstIndex + BLOCK_SIZE) > dst.length)
{
throw new IOException("output buffer too short");
}
encryptBlock(src, srcIndex, dst, dstIndex);
}
/**
* Method to encrypt the block at the given index.<br>
* The encrypted block goes directly to the source array at the given<br>
* index.<br>
* <br>
* This method does not perform any error checking. This could be<br>
* usefull when code calling this method performs size checks already or<br>
* perfroming steps to ensure nothing can go wrong.<br>
* <br>
* If you want error checking use {@link #tryEncryptBlock(byte[], int)}.
* @param src source array with the plain data
* @param srcIndex index where the block to encrypt is located
*/
public void encryptBlock(byte[] src, int srcIndex)
{
encryptBlock(src, srcIndex, src, srcIndex);
}
/**
* Method to encrypt the block at the given index.<br>
* The encrypted block goes to the destination array at the given index.<br>
* <br>
* This method does not perform any error checking. This could be<br>
* usefull when code calling this method performs size checks already or<br>
* perfroming steps to ensure nothing can go wrong.<br>
* <br>
* If you want error checking use {@link #tryEncryptBlock(byte[], int, byte[], int)}.
* @param src source array with the plain data
* @param srcIndex index where the block to encrypt is located
* @param dst destination array the encryption will go to
* @param dstIndex index where the encrypted block is to be stored
*/
public void encryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex)
{
int xl = bytesTo32bits(src, srcIndex);
int xr = bytesTo32bits(src, srcIndex + 4);
xl ^= P[0];
for (int i = 1; i < ROUNDS; i += 2)
{
xr ^= func(xl) ^ P[i];
xl ^= func(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
xr ^= func(xl) ^ P[1];
xl ^= func(xr) ^ P[2];
xr ^= func(xl) ^ P[3];
xl ^= func(xr) ^ P[4];
xr ^= func(xl) ^ P[5];
xl ^= func(xr) ^ P[6];
xr ^= func(xl) ^ P[7];
xl ^= func(xr) ^ P[8];
xr ^= func(xl) ^ P[9];
xl ^= func(xr) ^ P[10];
xr ^= func(xl) ^ P[11];
xl ^= func(xr) ^ P[12];
xr ^= func(xl) ^ P[13];
xl ^= func(xr) ^ P[14];
xr ^= func(xl) ^ P[15];
xl ^= func(xr) ^ P[16];
xr ^= P[17];
bits32ToBytes(xr, dst, dstIndex);
bits32ToBytes(xl, dst, dstIndex + 4);
}
/**
* Decrypt the given input starting at the given offset and place the result in the provided buffer starting at the given offset. The input will be an exact multiple of our blocksize.
* @param src
* @param srcIndex
* @param dst
* @param dstIndex
* Method to decrypt the block at the given index.<br>
* The decrypted block goes directly to the source array at the given<br>
* index.
* @param src source array with the encrypted data
* @param srcIndex index where the block to decrypt is located
* @throws IllegalStateException The cipher was not yet initialized
* @throws IOException The source array is too small to hold a block at the given index
*/
private void decryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex)
public void tryDecryptBlock(byte[] src, int srcIndex) throws IOException
{
if (workingKey == null)
{
throw new IllegalStateException("Blowfish not initialized");
}
if ((srcIndex + BLOCK_SIZE) > src.length)
{
throw new IOException("input buffer too short");
}
decryptBlock(src, srcIndex);
}
/**
* Method to decrypt the block at the given index.<br>
* The decrypted block goes to the destination array at the given index.<br>
* @param src source array with the plain data
* @param srcIndex index where the block to decrypt is located
* @param dst destination array the decryption will go to
* @param dstIndex index where the decrypted block is to be stored
* @throws IllegalStateException The cipher was not yet initialized
* @throws IOException The source or destination array is too small to hold a block at the given index
*/
public void tryDecryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) throws IOException
{
if (workingKey == null)
{
throw new IllegalStateException("Blowfish not initialized");
}
if ((srcIndex + BLOCK_SIZE) > src.length)
{
throw new IOException("input buffer too short");
}
if ((dstIndex + BLOCK_SIZE) > src.length)
{
throw new IOException("output buffer too short");
}
decryptBlock(src, srcIndex, dst, dstIndex);
}
/**
* Method to decrypt the block at the given index.<br>
* The decrypted block goes directly to the source array at the given<br>
* index.<br>
* <br>
* This method does not perform any error checking. This could be<br>
* usefull when code calling this method performs size checks already or<br>
* perfroming steps to ensure nothing can go wrong.<br>
* <br>
* If you want error checking use {@link #tryDecryptBlock(byte[], int)}.
* @param src source array with the encrypted data
* @param srcIndex index where the block to decrypt is located
*/
public void decryptBlock(byte[] src, int srcIndex)
{
decryptBlock(src, srcIndex, src, srcIndex);
}
/**
* Method to decrypt the block at the given index.<br>
* The decrypted block goes to the destination array at the given index.<br>
* <br>
* This method does not perform any error checking. This could be<br>
* usefull when code calling this method performs size checks already or<br>
* perfroming steps to ensure nothing can go wrong.<br>
* <br>
* If you want error checking use {@link #tryDecryptBlock(byte[], int, byte[], int)}.
* @param src source array with the plain data
* @param srcIndex index where the block to decrypt is located
* @param dst destination array the decryption will go to
* @param dstIndex index where the decrypted block is to be stored
* @throws IllegalStateException The cipher was not yet initialized
*/
public void decryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex)
{
int xl = bytesTo32bits(src, srcIndex);
int xr = bytesTo32bits(src, srcIndex + 4);
xl ^= P[ROUNDS + 1];
for (int i = ROUNDS; i > 0; i -= 2)
{
xr ^= func(xl) ^ P[i];
xl ^= func(xr) ^ P[i - 1];
}
xl ^= P[17];
xr ^= func(xl) ^ P[16];
xl ^= func(xr) ^ P[15];
xr ^= func(xl) ^ P[14];
xl ^= func(xr) ^ P[13];
xr ^= func(xl) ^ P[12];
xl ^= func(xr) ^ P[11];
xr ^= func(xl) ^ P[10];
xl ^= func(xr) ^ P[9];
xr ^= func(xl) ^ P[8];
xl ^= func(xr) ^ P[7];
xr ^= func(xl) ^ P[6];
xl ^= func(xr) ^ P[5];
xr ^= func(xl) ^ P[4];
xl ^= func(xr) ^ P[3];
xr ^= func(xl) ^ P[2];
xl ^= func(xr) ^ P[1];
xr ^= P[0];
bits32ToBytes(xr, dst, dstIndex);
bits32ToBytes(xl, dst, dstIndex + 4);
}
private int bytesTo32bits(byte[] b, int i)
/**
* Method to construct an int from the source array.<br>
* 4 bytes are used from the given index.<br>
* <br>
* This method does not do any error checking.
* @param src source array with the bytes
* @param srcIndex the index to extract the int from
* @return the extracted integer
*/
private int bytesTo32bits(byte[] src, int srcIndex)
{
return ((b[i + 3] & 0xff) << 24) | ((b[i + 2] & 0xff) << 16) | ((b[i + 1] & 0xff) << 8) | (b[i] & 0xff);
return ((src[srcIndex + 3] & 0xff) << 24) | ((src[srcIndex + 2] & 0xff) << 16) | ((src[srcIndex + 1] & 0xff) << 8) | (src[srcIndex] & 0xff);
}
private void bits32ToBytes(int in, byte[] b, int offset)
/**
* Method to decompose an int into a byte array.<br>
* <br>
* This method does not do any error checking.
* @param in the integer to decompose into bytes
* @param dst the destination array the decomposed int goes to
* @param dstIndex the index in the destination array the decomposed int will be stored at
*/
private void bits32ToBytes(int in, byte[] dst, int dstIndex)
{
b[offset] = (byte) in;
b[offset + 1] = (byte) (in >> 8);
b[offset + 2] = (byte) (in >> 16);
b[offset + 3] = (byte) (in >> 24);
dst[dstIndex] = (byte) in;
dst[dstIndex + 1] = (byte) (in >> 8);
dst[dstIndex + 2] = (byte) (in >> 16);
dst[dstIndex + 3] = (byte) (in >> 24);
}
}

View File

@@ -0,0 +1,148 @@
/*
* 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 org.l2jmobius.commons.util.crypt;
import javax.crypto.SecretKey;
import org.l2jmobius.commons.network.ICrypt;
import org.l2jmobius.commons.util.Rnd;
import io.netty.buffer.ByteBuf;
/**
* @author NosBit
*/
public class LoginCrypt implements ICrypt
{
private static final byte[] STATIC_BLOWFISH_KEY =
{
(byte) 0x6b,
(byte) 0x60,
(byte) 0xcb,
(byte) 0x5b,
(byte) 0x82,
(byte) 0xce,
(byte) 0x90,
(byte) 0xb1,
(byte) 0xcc,
(byte) 0x2b,
(byte) 0x6c,
(byte) 0x55,
(byte) 0x6c,
(byte) 0x6c,
(byte) 0x6c,
(byte) 0x6c
};
private static final BlowfishEngine STATIC_BLOWFISH_ENGINE = new BlowfishEngine();
static
{
STATIC_BLOWFISH_ENGINE.init(STATIC_BLOWFISH_KEY);
}
private final BlowfishEngine _blowfishEngine = new BlowfishEngine();
private boolean _static = true;
public LoginCrypt(SecretKey blowfishKey)
{
_blowfishEngine.init(blowfishKey.getEncoded());
}
/*
* (non-Javadoc)
* @see com.l2jserver.commons.network.ICrypt#encrypt(io.netty.buffer.ByteBuf)
*/
@Override
public void encrypt(ByteBuf buf)
{
// Checksum & XOR Key or Checksum only
buf.writeZero(_static ? 16 : 12);
// Padding
buf.writeZero(8 - (buf.readableBytes() % 8));
if (_static)
{
_static = false;
int key = Rnd.nextInt();
buf.skipBytes(4); // The first 4 bytes are ignored
while (buf.readerIndex() < (buf.writerIndex() - 8))
{
int data = buf.readIntLE();
key += data;
data ^= key;
buf.setIntLE(buf.readerIndex() - 4, data);
}
buf.setIntLE(buf.readerIndex(), key);
buf.resetReaderIndex();
final byte[] block = new byte[8];
while (buf.isReadable(8))
{
buf.readBytes(block);
STATIC_BLOWFISH_ENGINE.encryptBlock(block, 0);
buf.setBytes(buf.readerIndex() - block.length, block);
}
}
else
{
int checksum = 0;
while (buf.isReadable(8))
{
checksum ^= buf.readIntLE();
}
buf.setIntLE(buf.readerIndex(), checksum);
buf.resetReaderIndex();
final byte[] block = new byte[8];
while (buf.isReadable(8))
{
buf.readBytes(block);
_blowfishEngine.encryptBlock(block, 0);
buf.setBytes(buf.readerIndex() - block.length, block);
}
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.commons.network.ICrypt#decrypt(io.netty.buffer.ByteBuf)
*/
@Override
public void decrypt(ByteBuf buf)
{
// Packet size must be multiple of 8
if ((buf.readableBytes() % 8) != 0)
{
buf.clear();
return;
}
final byte[] block = new byte[8];
while (buf.isReadable(8))
{
buf.readBytes(block);
_blowfishEngine.decryptBlock(block, 0);
buf.setBytes(buf.readerIndex() - block.length, block);
}
// TODO: verify checksum also dont forget!
}
}

View File

@@ -14,29 +14,27 @@
* 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 org.l2jmobius.commons.crypt;
import java.io.IOException;
import java.util.logging.Logger;
package org.l2jmobius.commons.util.crypt;
/**
* @version $Revision: 1.3.4.1 $ $Date: 2005/03/27 15:30:09 $
* Class to use a blowfish cipher with ECB processing.<br>
* Static methods are present to append/check the checksum of<br>
* packets exchanged between the following partners:<br>
* Login Server <-> Game Client<br>
* Login Server <-> Game Server<br>
* Also a static method is provided for the initial xor encryption between Login Server <-> Game Client.
*/
public class NewCrypt
{
protected static final Logger LOGGER = Logger.getLogger(NewCrypt.class.getName());
BlowfishEngine _crypt;
BlowfishEngine _decrypt;
private final BlowfishEngine _cipher;
/**
* @param blowfishKey
*/
public NewCrypt(byte[] blowfishKey)
{
_crypt = new BlowfishEngine();
_crypt.init(true, blowfishKey);
_decrypt = new BlowfishEngine();
_decrypt.init(false, blowfishKey);
_cipher = new BlowfishEngine();
_cipher.init(blowfishKey);
}
public NewCrypt(String key)
@@ -44,11 +42,24 @@ public class NewCrypt
this(key.getBytes());
}
/**
* Equivalent to calling {@link #verifyChecksum(byte[], int, int)} with parameters (raw, 0, raw.length)
* @param raw data array to be verified
* @return true when the checksum of the data is valid, false otherwise
*/
public static boolean verifyChecksum(byte[] raw)
{
return verifyChecksum(raw, 0, raw.length);
}
/**
* Method to verify the checksum of a packet received by login server from game client.<br>
* This is also used for game server <-> login server communication.
* @param raw data array to be verified
* @param offset at which offset to start verifying
* @param size number of bytes to verify
* @return true if the checksum of the data is valid, false otherwise
*/
public static boolean verifyChecksum(byte[] raw, int offset, int size)
{
// check if size is multiple of 4 and if there is more then only the checksum
@@ -80,11 +91,21 @@ public class NewCrypt
return check == chksum;
}
/**
* Equivalent to calling {@link #appendChecksum(byte[], int, int)} with parameters (raw, 0, raw.length)
* @param raw data array to compute the checksum from
*/
public static void appendChecksum(byte[] raw)
{
appendChecksum(raw, 0, raw.length);
}
/**
* Method to append packet checksum at the end of the packet.
* @param raw data array to compute the checksum from
* @param offset offset where to start in the data array
* @param size number of bytes to compute the checksum from
*/
public static void appendChecksum(byte[] raw, int offset, int size)
{
long chksum = 0;
@@ -114,7 +135,8 @@ public class NewCrypt
}
/**
* Packet is first XOR encoded with <code>key</code> Then, the last 4 bytes are overwritten with the the XOR "key". Thus this assume that there is enough room for the key to fit without overwriting data.
* Packet is first XOR encoded with <code>key</code> then, the last 4 bytes are overwritten with the the XOR "key".<br>
* Thus this assume that there is enough room for the key to fit without overwriting data.
* @param raw The raw bytes to be encrypted
* @param key The 4 bytes (int) XOR key
*/
@@ -124,13 +146,14 @@ public class NewCrypt
}
/**
* Packet is first XOR encoded with <code>key</code> Then, the last 4 bytes are overwritten with the the XOR "key". Thus this assume that there is enough room for the key to fit without overwriting data.
* Packet is first XOR encoded with <code>key</code> then, the last 4 bytes are overwritten with the the XOR "key".<br>
* Thus this assume that there is enough room for the key to fit without overwriting data.
* @param raw The raw bytes to be encrypted
* @param offset The begining of the data to be encrypted
* @param offset The beginning of the data to be encrypted
* @param size Length of the data to be encrypted
* @param key The 4 bytes (int) XOR key
*/
public static void encXORPass(byte[] raw, int offset, int size, int key)
static void encXORPass(byte[] raw, int offset, int size, int key)
{
final int stop = size - 8;
int pos = 4 + offset;
@@ -160,55 +183,36 @@ public class NewCrypt
raw[pos++] = (byte) ((ecx >> 24) & 0xFF);
}
public byte[] decrypt(byte[] raw) throws IOException
/**
* Method to decrypt using Blowfish-Blockcipher in ECB mode.<br>
* The results will be directly placed inside {@code raw} array.<br>
* This method does not do any error checking, since the calling code<br>
* should ensure sizes.
* @param raw the data array to be decrypted
* @param offset the offset at which to start decrypting
* @param size the number of bytes to be decrypted
*/
public void decrypt(byte[] raw, int offset, int size)
{
final byte[] result = new byte[raw.length];
final int count = raw.length / 8;
for (int i = 0; i < count; i++)
for (int i = offset; i < (offset + size); i += 8)
{
_decrypt.processBlock(raw, i * 8, result, i * 8);
_cipher.decryptBlock(raw, i);
}
return result;
}
public void decrypt(byte[] raw, int offset, int size) throws IOException
/**
* Method to encrypt using Blowfish-Blockcipher in ECB mode.<br>
* The results will be directly placed inside {@code raw} array.<br>
* This method does not do any error checking, since the calling code should ensure sizes.
* @param raw the data array to be decrypted
* @param offset the offset at which to start decrypting
* @param size the number of bytes to be decrypted
*/
public void crypt(byte[] raw, int offset, int size)
{
final byte[] result = new byte[size];
final int count = size / 8;
for (int i = 0; i < count; i++)
for (int i = offset; i < (offset + size); i += 8)
{
_decrypt.processBlock(raw, offset + (i * 8), result, i * 8);
_cipher.encryptBlock(raw, i);
}
// TODO can the crypt and decrypt go direct to the array
System.arraycopy(result, 0, raw, offset, size);
}
public byte[] crypt(byte[] raw) throws IOException
{
final int count = raw.length / 8;
final byte[] result = new byte[raw.length];
for (int i = 0; i < count; i++)
{
_crypt.processBlock(raw, i * 8, result, i * 8);
}
return result;
}
public void crypt(byte[] raw, int offset, int size) throws IOException
{
final int count = size / 8;
final byte[] result = new byte[size];
for (int i = 0; i < count; i++)
{
_crypt.processBlock(raw, offset + (i * 8), result, i * 8);
}
// TODO can the crypt and decrypt go direct to the array
System.arraycopy(result, 0, raw, offset, size);
}
}

View File

@@ -14,16 +14,19 @@
* 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 org.l2jmobius.commons.crypt;
package org.l2jmobius.commons.util.crypt;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyPair;
import java.security.interfaces.RSAPublicKey;
import java.util.logging.Logger;
public class ScrambledKeyPair
{
public KeyPair _pair;
public byte[] _scrambledModulus;
private static final Logger LOGGER = Logger.getLogger(ScrambledKeyPair.class.getName());
private final KeyPair _pair;
private final byte[] _scrambledModulus;
public ScrambledKeyPair(KeyPair pPair)
{
@@ -41,7 +44,6 @@ public class ScrambledKeyPair
System.arraycopy(scrambledMod, 1, temp, 0, 0x80);
scrambledMod = temp;
}
// step 1 : 0x4d-0x50 <-> 0x00-0x04
for (int i = 0; i < 4; i++)
{
@@ -49,25 +51,38 @@ public class ScrambledKeyPair
scrambledMod[0x00 + i] = scrambledMod[0x4d + i];
scrambledMod[0x4d + i] = temp;
}
// step 2 : xor first 0x40 bytes with last 0x40 bytes
for (int i = 0; i < 0x40; i++)
{
scrambledMod[i] = (byte) (scrambledMod[i] ^ scrambledMod[0x40 + i]);
}
// step 3 : xor bytes 0x0d-0x10 with bytes 0x34-0x38
for (int i = 0; i < 4; i++)
{
scrambledMod[0x0d + i] = (byte) (scrambledMod[0x0d + i] ^ scrambledMod[0x34 + i]);
}
// step 4 : xor last 0x40 bytes with first 0x40 bytes
for (int i = 0; i < 0x40; i++)
{
scrambledMod[0x40 + i] = (byte) (scrambledMod[0x40 + i] ^ scrambledMod[i]);
}
LOGGER.finer("Modulus was scrambled");
return scrambledMod;
}
public byte[] getScrambledModulus()
{
return _scrambledModulus;
}
public Key getPrivateKey()
{
return _pair.getPrivate();
}
public Key getPublicKey()
{
return _pair.getPublic();
}
}

View File

@@ -17,12 +17,10 @@
package org.l2jmobius.gameserver;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
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.LogManager;
import java.util.logging.Logger;
@@ -31,8 +29,6 @@ import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.enums.ServerMode;
import org.l2jmobius.commons.mmocore.SelectorConfig;
import org.l2jmobius.commons.mmocore.SelectorThread;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.commons.util.DeadlockDetector;
import org.l2jmobius.commons.util.Util;
@@ -125,8 +121,8 @@ import org.l2jmobius.gameserver.model.siege.clanhalls.BanditStrongholdSiege;
import org.l2jmobius.gameserver.model.siege.clanhalls.DevastatedCastle;
import org.l2jmobius.gameserver.model.siege.clanhalls.FortressOfResistance;
import org.l2jmobius.gameserver.model.spawn.AutoSpawn;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.GamePacketHandler;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.loginserver.LoginServerNetworkManager;
import org.l2jmobius.gameserver.script.EventDroplist;
import org.l2jmobius.gameserver.script.faenor.FaenorScriptEngine;
import org.l2jmobius.gameserver.scripting.ScriptEngineManager;
@@ -138,14 +134,16 @@ public class GameServer
{
private static final Logger LOGGER = Logger.getLogger(GameServer.class.getName());
private static SelectorThread<GameClient> _selectorThread;
private static LoginServerThread _loginThread;
private static GamePacketHandler _gamePacketHandler;
private static TelnetStatusThread _statusServer;
private static GameServer INSTANCE;
public static final Calendar dateTimeServerStarted = Calendar.getInstance();
public long getUsedMemoryMB()
{
return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1048576;
}
public GameServer() throws Exception
{
final long serverLoadStart = Chronos.currentTimeMillis();
@@ -488,17 +486,6 @@ public class GameServer
{
PrecautionaryRestartManager.getInstance();
}
System.gc();
Util.printSection("Info");
LOGGER.info("Maximum Numbers of Connected Players: " + Config.MAXIMUM_ONLINE_USERS);
LOGGER.info("GameServer Started, free memory " + (((Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory()) + Runtime.getRuntime().freeMemory()) / 1048576) + " Mb of " + (Runtime.getRuntime().maxMemory() / 1048576) + " Mb");
LOGGER.info("Used memory: " + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1048576) + " MB");
Util.printSection("Status");
LOGGER.info("Server Loaded in " + ((Chronos.currentTimeMillis() - serverLoadStart) / 1000) + " seconds.");
// Load telnet status
Util.printSection("Telnet");
if (Config.IS_TELNET_ENABLED)
@@ -512,47 +499,24 @@ public class GameServer
}
Util.printSection("Login");
_loginThread = LoginServerThread.getInstance();
_loginThread.start();
ClientNetworkManager.getInstance().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;
_gamePacketHandler = new GamePacketHandler();
_selectorThread = new SelectorThread<>(sc, _gamePacketHandler, _gamePacketHandler, _gamePacketHandler);
InetAddress bindAddress = null;
if (!Config.GAMESERVER_HOSTNAME.equals("*"))
if (Boolean.getBoolean("newLoginServer"))
{
try
{
bindAddress = InetAddress.getByName(Config.GAMESERVER_HOSTNAME);
}
catch (UnknownHostException e1)
{
LOGGER.warning("The GameServer bind address is invalid, using all avaliable IPs. Reason: " + e1);
}
LoginServerNetworkManager.getInstance().connect();
}
else
{
LoginServerThread.getInstance().start();
}
try
{
_selectorThread.openServerSocket(bindAddress, Config.PORT_GAME);
}
catch (IOException e)
{
LOGGER.severe("Failed to open server socket. Reason: " + e);
System.exit(1);
}
_selectorThread.start();
}
public static SelectorThread<GameClient> getSelectorThread()
{
return _selectorThread;
System.gc();
final long totalMem = Runtime.getRuntime().maxMemory() / 1048576;
LOGGER.info(getClass().getSimpleName() + ": Started, using " + getUsedMemoryMB() + " of " + totalMem + " MB total memory.");
LOGGER.info(getClass().getSimpleName() + ": Maximum number of connected players is " + Config.MAXIMUM_ONLINE_USERS + ".");
LOGGER.info(getClass().getSimpleName() + ": Server loaded in " + ((Chronos.currentTimeMillis() - serverLoadStart) / 1000) + " seconds.");
Toolkit.getDefaultToolkit().beep();
}
public static void main(String[] args) throws Exception

View File

@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
@@ -31,29 +32,31 @@ import java.security.spec.RSAPublicKeySpec;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.crypt.NewCrypt;
import org.l2jmobius.commons.network.BaseSendablePacket;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.commons.util.crypt.NewCrypt;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.ConnectionState;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.gameserverpackets.AuthRequest;
import org.l2jmobius.gameserver.network.gameserverpackets.BlowFishKey;
import org.l2jmobius.gameserver.network.gameserverpackets.ChangeAccessLevel;
import org.l2jmobius.gameserver.network.gameserverpackets.GameServerBasePacket;
import org.l2jmobius.gameserver.network.gameserverpackets.PlayerAuthRequest;
import org.l2jmobius.gameserver.network.gameserverpackets.PlayerInGame;
import org.l2jmobius.gameserver.network.gameserverpackets.PlayerLogout;
import org.l2jmobius.gameserver.network.gameserverpackets.ServerStatus;
import org.l2jmobius.gameserver.network.loginserverpackets.AuthResponse;
import org.l2jmobius.gameserver.network.loginserverpackets.InitLS;
import org.l2jmobius.gameserver.network.loginserverpackets.KickPlayer;
import org.l2jmobius.gameserver.network.loginserverpackets.LoginServerFail;
import org.l2jmobius.gameserver.network.loginserverpackets.PlayerAuthResponse;
import org.l2jmobius.gameserver.network.loginserverpackets.game.AuthRequest;
import org.l2jmobius.gameserver.network.loginserverpackets.game.BlowFishKey;
import org.l2jmobius.gameserver.network.loginserverpackets.game.ChangeAccessLevel;
import org.l2jmobius.gameserver.network.loginserverpackets.game.PlayerAuthRequest;
import org.l2jmobius.gameserver.network.loginserverpackets.game.PlayerInGame;
import org.l2jmobius.gameserver.network.loginserverpackets.game.PlayerLogout;
import org.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus;
import org.l2jmobius.gameserver.network.loginserverpackets.login.AuthResponse;
import org.l2jmobius.gameserver.network.loginserverpackets.login.InitLS;
import org.l2jmobius.gameserver.network.loginserverpackets.login.KickPlayer;
import org.l2jmobius.gameserver.network.loginserverpackets.login.LoginServerFail;
import org.l2jmobius.gameserver.network.loginserverpackets.login.PlayerAuthResponse;
import org.l2jmobius.gameserver.network.serverpackets.AuthLoginFail;
import org.l2jmobius.gameserver.network.serverpackets.CharSelectInfo;
@@ -63,12 +66,10 @@ public class LoginServerThread extends Thread
/** The LoginServerThread singleton */
private static final int REVISION = 0x0102;
private RSAPublicKey _publicKey;
private final String _hostname;
private final int _port;
private final int _gamePort;
private Socket _loginSocket;
private InputStream _in;
private OutputStream _out;
/**
@@ -76,23 +77,21 @@ public class LoginServerThread extends Thread
* It is first initialized with a unified key:<br>
* "_;v.]05-31!|+-%xT!^[$\00"<br>
* and then after handshake, with a new key sent by<br>
* loginserver during the handshake. This new key is stored<br>
* in {@link #_blowfishKey}
* login server during the handshake. This new key is stored<br>
* in blowfishKey
*/
private NewCrypt _blowfish;
private byte[] _blowfishKey;
private byte[] _hexID;
private final boolean _acceptAlternate;
private int _requestID;
private int _serverID;
private final boolean _reserveHost;
private int _maxPlayer;
private final List<WaitingClient> _waitingClients;
private final Map<String, GameClient> _accountsInGameServer;
private final Set<WaitingClient> _waitingClients = ConcurrentHashMap.newKeySet();
private final Map<String, GameClient> _accountsInGameServer = new ConcurrentHashMap<>();
private int _status;
private String _serverName;
private final String _gameExternalHost;
private final String _gameInternalHost;
private final List<String> _subnets;
private final List<String> _hosts;
public LoginServerThread()
{
@@ -112,17 +111,15 @@ public class LoginServerThread extends Thread
}
_acceptAlternate = Config.ACCEPT_ALTERNATE_ID;
_reserveHost = Config.RESERVE_HOST_ON_LOGIN;
_gameExternalHost = Config.EXTERNAL_HOSTNAME;
_gameInternalHost = Config.INTERNAL_HOSTNAME;
_waitingClients = new ArrayList<>();
_accountsInGameServer = new ConcurrentHashMap<>();
_subnets = Config.GAME_SERVER_SUBNETS;
_hosts = Config.GAME_SERVER_HOSTS;
_maxPlayer = Config.MAXIMUM_ONLINE_USERS;
}
@Override
public void run()
{
while (!_interrupted)
while (!isInterrupted())
{
int lengthHi = 0;
int lengthLo = 0;
@@ -131,112 +128,99 @@ public class LoginServerThread extends Thread
try
{
// Connection
LOGGER.info("Connecting to login on " + _hostname + ":" + _port);
LOGGER.info(getClass().getSimpleName() + ": Connecting to login on " + _hostname + ":" + _port);
_loginSocket = new Socket(_hostname, _port);
_in = _loginSocket.getInputStream();
if (_out != null)
{
synchronized (_out) // avoids tow threads writing in the mean time
{
_out = new BufferedOutputStream(_loginSocket.getOutputStream());
}
}
else
{
_out = new BufferedOutputStream(_loginSocket.getOutputStream());
}
final InputStream in = _loginSocket.getInputStream();
_out = new BufferedOutputStream(_loginSocket.getOutputStream());
// init Blowfish
_blowfishKey = generateHex(40);
final byte[] blowfishKey = generateHex(40);
_blowfish = new NewCrypt("_;v.]05-31!|+-%xT!^[$\00");
while (!_interrupted)
while (!isInterrupted())
{
lengthLo = _in.read();
lengthHi = _in.read();
lengthLo = in.read();
lengthHi = in.read();
length = (lengthHi * 256) + lengthLo;
if (lengthHi < 0)
{
LOGGER.info("LoginServerThread: Login terminated the connection.");
LOGGER.finer(getClass().getSimpleName() + ": Login terminated the connection.");
break;
}
final byte[] incoming = new byte[length];
incoming[0] = (byte) lengthLo;
incoming[1] = (byte) lengthHi;
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, 2, length - 2);
receivedBytes = receivedBytes + newBytes;
newBytes = in.read(incoming, receivedBytes, left);
receivedBytes += newBytes;
left -= newBytes;
}
if (receivedBytes != (length - 2))
{
LOGGER.warning("Incomplete Packet is sent to the server, closing connection.(LS)");
LOGGER.warning(getClass().getSimpleName() + ": Incomplete Packet is sent to the server, closing connection.(LS)");
break;
}
byte[] decrypt = new byte[length - 2];
System.arraycopy(incoming, 2, decrypt, 0, decrypt.length);
// decrypt if we have a key
decrypt = _blowfish.decrypt(decrypt);
checksumOk = NewCrypt.verifyChecksum(decrypt);
_blowfish.decrypt(incoming, 0, incoming.length);
checksumOk = NewCrypt.verifyChecksum(incoming);
if (!checksumOk)
{
LOGGER.warning("Incorrect packet checksum, ignoring packet (LS)");
LOGGER.warning(getClass().getSimpleName() + ": Incorrect packet checksum, ignoring packet (LS)");
break;
}
final int packetType = decrypt[0] & 0xff;
final int packetType = incoming[0] & 0xff;
switch (packetType)
{
case 0x00:
{
final InitLS init = new InitLS(decrypt);
final InitLS init = new InitLS(incoming);
if (init.getRevision() != REVISION)
{
// TODO: revision mismatch
LOGGER.warning("/!\\ Revision mismatch between LS and GS /!\\");
break;
}
RSAPublicKey publicKey;
try
{
final KeyFactory kfac = KeyFactory.getInstance("RSA");
final BigInteger modulus = new BigInteger(init.getRSAKey());
final RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
_publicKey = (RSAPublicKey) kfac.generatePublic(kspec1);
publicKey = (RSAPublicKey) kfac.generatePublic(kspec1);
}
catch (GeneralSecurityException e)
{
LOGGER.warning("Trouble while init the public key send by login");
LOGGER.warning(getClass().getSimpleName() + ": Trouble while init the public key send by login");
break;
}
// send the blowfish key through the rsa encryption
final BlowFishKey bfk = new BlowFishKey(_blowfishKey, _publicKey);
sendPacket(bfk);
// now, only accept paket with the new encryption
_blowfish = new NewCrypt(_blowfishKey);
final AuthRequest ar = new AuthRequest(_requestID, _acceptAlternate, _hexID, _gameExternalHost, _gameInternalHost, _gamePort, _reserveHost, _maxPlayer);
sendPacket(ar);
sendPacket(new BlowFishKey(blowfishKey, publicKey));
// now, only accept packet with the new encryption
_blowfish = new NewCrypt(blowfishKey);
sendPacket(new AuthRequest(_requestID, _acceptAlternate, _hexID, _gamePort, _reserveHost, _maxPlayer, _subnets, _hosts));
break;
}
case 0x01:
{
final LoginServerFail lsf = new LoginServerFail(decrypt);
LOGGER.info("Damn! Registeration Failed: " + lsf.getReasonString());
final LoginServerFail lsf = new LoginServerFail(incoming);
LOGGER.info(getClass().getSimpleName() + ": Damn! Registeration Failed: " + lsf.getReasonString());
// login will close the connection here
break;
}
case 0x02:
{
final AuthResponse aresp = new AuthResponse(decrypt);
_serverID = aresp.getServerId();
final AuthResponse aresp = new AuthResponse(incoming);
final int serverID = aresp.getServerId();
_serverName = aresp.getServerName();
Config.saveHexid(_serverID, hexToString(_hexID));
LOGGER.info("Registered on login as Server " + _serverID + " : " + _serverName);
Config.saveHexid(serverID, hexToString(_hexID));
LOGGER.info(getClass().getSimpleName() + ": Registered on login as Server " + serverID + ": " + _serverName);
final ServerStatus st = new ServerStatus();
if (Config.SERVER_LIST_BRACKET)
{
@@ -285,7 +269,7 @@ public class LoginServerThread extends Thread
}
case 0x03:
{
final PlayerAuthResponse par = new PlayerAuthResponse(decrypt);
final PlayerAuthResponse par = new PlayerAuthResponse(incoming);
final String account = par.getAccount();
WaitingClient wcToRemove = null;
synchronized (_waitingClients)
@@ -304,17 +288,18 @@ public class LoginServerThread extends Thread
{
final PlayerInGame pig = new PlayerInGame(par.getAccount());
sendPacket(pig);
wcToRemove.gameClient.setState(ConnectionState.AUTHENTICATED);
wcToRemove.gameClient.setConnectionState(ConnectionState.AUTHENTICATED);
wcToRemove.gameClient.setSessionId(wcToRemove.session);
final CharSelectInfo cl = new CharSelectInfo(wcToRemove.account, wcToRemove.gameClient.getSessionId().playOkID1);
wcToRemove.gameClient.getConnection().sendPacket(cl);
wcToRemove.gameClient.sendPacket(cl);
wcToRemove.gameClient.setCharSelection(cl.getCharInfo());
}
else
{
LOGGER.warning("Session key is not correct. Closing connection for account " + wcToRemove.account + ".");
wcToRemove.gameClient.getConnection().sendPacket(new AuthLoginFail(1));
wcToRemove.gameClient.closeNow();
LOGGER.warning(getClass().getSimpleName() + ": Session key is not correct. Closing connection for account " + wcToRemove.account);
// wcToRemove.gameClient.getConnection().sendPacket(new LoginFail(LoginFail.SYSTEM_ERROR_LOGIN_LATER));
wcToRemove.gameClient.close(new AuthLoginFail(AuthLoginFail.SYSTEM_ERROR_LOGIN_LATER));
_accountsInGameServer.remove(wcToRemove.account);
}
_waitingClients.remove(wcToRemove);
}
@@ -322,7 +307,7 @@ public class LoginServerThread extends Thread
}
case 0x04:
{
final KickPlayer kp = new KickPlayer(decrypt);
final KickPlayer kp = new KickPlayer(incoming);
doKickPlayer(kp.getAccount());
break;
}
@@ -331,75 +316,74 @@ public class LoginServerThread extends Thread
}
catch (UnknownHostException e)
{
LOGGER.info("Deconnected from Login, Trying to reconnect:");
LOGGER.info(e.toString());
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": ", e);
}
catch (SocketException e)
{
LOGGER.warning(getClass().getSimpleName() + ": LoginServer not avaible, trying to reconnect...");
}
catch (IOException e)
{
LOGGER.info("Deconnected from Login, Trying to reconnect..");
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Disconnected from Login, Trying to reconnect: ", e);
}
finally
{
if (_out != null)
try
{
synchronized (_out) // avoids tow threads writing in the mean time
_loginSocket.close();
if (isInterrupted())
{
try
{
_loginSocket.close();
}
catch (Exception e)
{
}
return;
}
}
else
catch (Exception e)
{
try
{
_loginSocket.close();
}
catch (Exception e)
{
}
// Ignore.
}
}
try
{
Thread.sleep(5000); // 5 seconds
Thread.sleep(5000); // 5 seconds tempo.
}
catch (InterruptedException e)
catch (Exception e)
{
// Ignore.
}
}
}
/**
* Adds the waiting client and send request.
* @param acc the account
* @param client the game client
* @param key the session key
*/
public void addWaitingClientAndSendRequest(String acc, GameClient client, SessionKey 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 (IOException e)
{
LOGGER.warning("Error while sending player auth request");
LOGGER.warning(getClass().getSimpleName() + ": Error while sending player auth request");
}
}
/**
* Removes the waiting client.
* @param client the client
*/
public void removeWaitingClient(GameClient client)
{
WaitingClient toRemove = null;
synchronized (_waitingClients)
{
for (WaitingClient c : _waitingClients)
@@ -409,7 +393,6 @@ public class LoginServerThread extends Thread
toRemove = c;
}
}
if (toRemove != null)
{
_waitingClients.remove(toRemove);
@@ -417,6 +400,10 @@ public class LoginServerThread extends Thread
}
}
/**
* Send logout for the given account.
* @param account the account
*/
public void sendLogout(String account)
{
if (account == null)
@@ -430,7 +417,11 @@ public class LoginServerThread extends Thread
}
catch (IOException e)
{
LOGGER.warning("Error while sending logout packet to login: " + e.getMessage());
LOGGER.warning(getClass().getSimpleName() + ": Error while sending logout packet to login");
}
finally
{
_accountsInGameServer.remove(account);
}
}
@@ -480,42 +471,55 @@ public class LoginServerThread extends Thread
}
}
/**
* Method to generate a random sequence of bytes returned as byte array
* @param size number of random bytes to generate
* @return byte array with sequence of random bytes
*/
public static byte[] generateHex(int size)
{
final byte[] array = new byte[size];
Rnd.nextBytes(array);
// Don't allow 0s inside the array!
for (int i = 0; i < array.length; i++)
{
while (array[i] == 0)
{
array[i] = (byte) Rnd.get(Byte.MAX_VALUE);
}
}
return array;
}
/**
* @param sl
* @throws IOException
* Send packet.
* @param sl the sendable packet
* @throws IOException Signals that an I/O exception has occurred.
*/
private void sendPacket(GameServerBasePacket sl) throws IOException
private void sendPacket(BaseSendablePacket sl) throws IOException
{
if (_interrupted)
if (_blowfish == null)
{
return;
}
byte[] data = sl.getContent();
final byte[] data = sl.getContent();
NewCrypt.appendChecksum(data);
data = _blowfish.crypt(data);
_blowfish.crypt(data, 0, data.length);
final int len = data.length + 2;
if ((_out != null) && !_loginSocket.isClosed() && _loginSocket.isConnected())
synchronized (_out) // avoids tow threads writing in the mean time
{
synchronized (_out) // avoids tow threads writing in the mean time
{
_out.write(len & 0xff);
_out.write((len >> 8) & 0xff);
_out.write(data);
_out.flush();
}
_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)
@@ -525,6 +529,7 @@ public class LoginServerThread extends Thread
}
/**
* Gets the max player.
* @return Returns the maxPlayer.
*/
public int getMaxPlayer()
@@ -533,8 +538,9 @@ public class LoginServerThread extends Thread
}
/**
* @param id
* @param value
* Send server status.
* @param id the id
* @param value the value
*/
public void sendServerStatus(int id, int value)
{
@@ -546,6 +552,7 @@ public class LoginServerThread extends Thread
}
catch (IOException e)
{
// Ignore.
}
}
@@ -657,6 +664,12 @@ public class LoginServerThread extends Thread
public GameClient 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, GameClient client, SessionKey key)
{
account = acc;

View File

@@ -39,8 +39,10 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
import org.l2jmobius.gameserver.model.sevensigns.SevenSigns;
import org.l2jmobius.gameserver.model.sevensigns.SevenSignsFestival;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.EventLoopGroupManager;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.gameserverpackets.ServerStatus;
import org.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus;
import org.l2jmobius.gameserver.network.serverpackets.ServerClose;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
@@ -322,13 +324,16 @@ public class Shutdown extends Thread
{
}
// saveData sends messages to exit players, so shutdown selector after it
try
{
// GameServer.getSelectorThread().setDaemon(true);
GameServer.getSelectorThread().shutdown();
ClientNetworkManager.getInstance().stop();
EventLoopGroupManager.getInstance().shutdown();
LOGGER.info("Game Server: Selector thread has been shut down.");
}
catch (Throwable t)
{
// ignore
}
// stop all threadpolls
@@ -539,7 +544,7 @@ public class Shutdown extends Thread
if (player.getClient() != null)
{
player.getClient().sendPacket(ServerClose.STATIC_PACKET);
player.getClient().close(0);
player.getClient().close(false);
player.getClient().setPlayer(null);
player.setClient(null);
}

View File

@@ -201,11 +201,11 @@ public class OfflineTradeTable
PlayerInstance player = null;
try
{
final GameClient client = new GameClient(null);
final GameClient client = new GameClient();
player = PlayerInstance.load(rs.getInt("charId"));
client.setPlayer(player);
client.setAccountName(player.getAccountName());
client.setState(ConnectionState.IN_GAME);
client.setConnectionState(ConnectionState.IN_GAME);
player.setClient(client);
player.setOfflineMode(true);
player.setOnlineStatus(false);

View File

@@ -33,7 +33,7 @@ import org.l2jmobius.gameserver.model.AccessLevel;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
@@ -302,7 +302,7 @@ public class AdminData implements IXmlReader
}
}
public static void broadcastToGMs(GameServerPacket packet)
public static void broadcastToGMs(IClientOutgoingPacket packet)
{
for (PlayerInstance gm : getInstance().getAllGms(true))
{

View File

@@ -71,7 +71,7 @@ public class AdminDisconnect implements IAdminCommandHandler
BuilderUtil.sendSysMessage(activeChar, "Character " + player.getName() + " disconnected from server.");
// Logout Character
player.sendPacket(new LeaveWorld());
player.sendPacket(LeaveWorld.STATIC_PACKET);
player.closeNetConnection();
}
}

View File

@@ -1195,12 +1195,12 @@ public class AdminEditChar implements IAdminCommandHandler
final Map<String, Integer> dualboxIPs = new HashMap<>();
for (PlayerInstance player : players)
{
if ((player.getClient() == null) || (player.getClient().getConnection() == null) || (player.getClient().getConnection().getInetAddress() == null) || (player.getClient().getConnection().getInetAddress().getHostAddress() == null))
if ((player.getClient() == null) || (player.getClient().getConnectionAddress() == null) || (player.getClient().getConnectionAddress() == null) || (player.getClient().getConnectionAddress().getHostAddress() == null))
{
continue;
}
ip = player.getClient().getConnection().getInetAddress().getHostAddress();
ip = player.getClient().getConnectionAddress().getHostAddress();
if (ipMap.get(ip) == null)
{
ipMap.put(ip, new ArrayList<PlayerInstance>());
@@ -1260,12 +1260,12 @@ public class AdminEditChar implements IAdminCommandHandler
for (PlayerInstance player : players)
{
if ((player.getClient() == null) || (player.getClient().getConnection() == null) || (player.getClient().getConnection().getInetAddress() == null) || (player.getClient().getConnection().getInetAddress().getHostAddress() == null))
if ((player.getClient() == null) || (player.getClient().getConnectionAddress() == null) || (player.getClient().getConnectionAddress() == null) || (player.getClient().getConnectionAddress().getHostAddress() == null))
{
continue;
}
ip = player.getClient().getConnection().getInetAddress().getHostAddress();
ip = player.getClient().getConnectionAddress().getHostAddress();
if (ip.equals(ipAdress))
{
name = player.getName();

View File

@@ -29,7 +29,7 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.Earthquake;
import org.l2jmobius.gameserver.network.serverpackets.ExRedSky;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
import org.l2jmobius.gameserver.network.serverpackets.SignsSky;
@@ -666,7 +666,7 @@ public class AdminEffects implements IAdminCommandHandler
*/
private void adminAtmosphere(String type, String state, PlayerInstance activeChar)
{
GameServerPacket packet = null;
IClientOutgoingPacket packet = null;
switch (type)
{

View File

@@ -23,9 +23,7 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.CharInfo;
import org.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
import org.l2jmobius.gameserver.util.BuilderUtil;
import org.l2jmobius.gameserver.util.IllegalPlayerAction;
import org.l2jmobius.gameserver.util.Util;
@@ -219,8 +217,7 @@ public class AdminEnchant implements IAdminCommandHandler
final InventoryUpdate iu = new InventoryUpdate();
iu.addModifiedItem(itemInstance);
player.sendPacket(iu);
player.broadcastPacket(new CharInfo(player));
player.sendPacket(new UserInfo(player));
player.broadcastUserInfo();
// informations
BuilderUtil.sendSysMessage(activeChar, "Changed enchantment of " + player.getName() + "'s " + itemInstance.getItem().getName() + " from " + curEnchant + " to " + ench + ".");

View File

@@ -22,7 +22,7 @@ import org.l2jmobius.Config;
import org.l2jmobius.gameserver.LoginServerThread;
import org.l2jmobius.gameserver.handler.IAdminCommandHandler;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.gameserverpackets.ServerStatus;
import org.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus;
import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
import org.l2jmobius.gameserver.util.BuilderUtil;

View File

@@ -238,7 +238,7 @@ public class SummonFriend implements ISkillHandler
final ConfirmDlg confirm = new ConfirmDlg(SystemMessageId.S1_WISHES_TO_SUMMON_YOU_FROM_S2_DO_YOU_ACCEPT.getId());
confirm.addString(activePlayer.getName());
confirm.addZoneName(activePlayer.getX(), activePlayer.getY(), activePlayer.getZ());
confirm.addTime(30000);
confirm.addTime(30000, targetPlayer);
confirm.addRequesterId(activePlayer.getObjectId());
targetPlayer.sendPacket(confirm);
}

View File

@@ -23,7 +23,7 @@ import java.util.logging.Logger;
import org.l2jmobius.gameserver.model.Duel;
import org.l2jmobius.gameserver.model.Effect;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
public class DuelManager
{
@@ -189,7 +189,7 @@ public class DuelManager
* @param player
* @param packet
*/
public void broadcastToOppositTeam(PlayerInstance player, GameServerPacket packet)
public void broadcastToOppositTeam(PlayerInstance player, IClientOutgoingPacket packet)
{
if ((player == null) || !player.isInDuel())
{

View File

@@ -31,7 +31,7 @@ import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
@@ -179,7 +179,7 @@ public class PetitionManager
return _type.toString().replace("_", " ");
}
public void sendPetitionerPacket(GameServerPacket responsePacket)
public void sendPetitionerPacket(IClientOutgoingPacket responsePacket)
{
if ((_petitioner == null) || !_petitioner.isOnline())
{
@@ -189,7 +189,7 @@ public class PetitionManager
_petitioner.sendPacket(responsePacket);
}
public void sendResponderPacket(GameServerPacket responsePacket)
public void sendResponderPacket(IClientOutgoingPacket responsePacket)
{
if ((_responder == null) || !_responder.isOnline())
{

View File

@@ -29,7 +29,7 @@ import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import org.l2jmobius.gameserver.network.serverpackets.ExCloseMPCC;
import org.l2jmobius.gameserver.network.serverpackets.ExOpenMPCC;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
@@ -147,7 +147,7 @@ public class CommandChannel
* Broadcast packet to every channel member
* @param gsp
*/
public void broadcastToChannelMembers(GameServerPacket gsp)
public void broadcastToChannelMembers(IClientOutgoingPacket gsp)
{
if ((_parties != null) && !_parties.isEmpty())
{

View File

@@ -37,7 +37,7 @@ import org.l2jmobius.gameserver.network.serverpackets.ExDuelEnd;
import org.l2jmobius.gameserver.network.serverpackets.ExDuelReady;
import org.l2jmobius.gameserver.network.serverpackets.ExDuelStart;
import org.l2jmobius.gameserver.network.serverpackets.ExDuelUpdateUserInfo;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
@@ -673,7 +673,7 @@ public class Duel
* Broadcast a packet to the challanger team.
* @param packet the packet
*/
public void broadcastToTeam1(GameServerPacket packet)
public void broadcastToTeam1(IClientOutgoingPacket packet)
{
if (_playerA == null)
{
@@ -697,7 +697,7 @@ public class Duel
* Broadcast a packet to the challenged team.
* @param packet the packet
*/
public void broadcastToTeam2(GameServerPacket packet)
public void broadcastToTeam2(IClientOutgoingPacket packet)
{
if (_playerB == null)
{

View File

@@ -176,7 +176,7 @@ public class MacroList
}
catch (Exception e)
{
LOGGER.info("Player: " + _owner.getName() + " IP:" + _owner.getClient().getConnection().getInetAddress().getHostAddress() + " try to use bug with macros");
LOGGER.info("Player: " + _owner.getName() + " IP:" + _owner.getClient().getConnectionAddress().getHostAddress() + " trird to use bug with macros.");
LOGGER.warning("could not store macro: " + e);
}
}

View File

@@ -42,7 +42,7 @@ import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import org.l2jmobius.gameserver.network.serverpackets.ExCloseMPCC;
import org.l2jmobius.gameserver.network.serverpackets.ExOpenMPCC;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.PartyMemberPosition;
import org.l2jmobius.gameserver.network.serverpackets.PartySmallWindowAdd;
import org.l2jmobius.gameserver.network.serverpackets.PartySmallWindowAll;
@@ -282,7 +282,7 @@ public class Party
* Broadcasts packet to every party member
* @param msg
*/
public void broadcastToPartyMembers(GameServerPacket msg)
public void broadcastToPartyMembers(IClientOutgoingPacket msg)
{
for (PlayerInstance member : _members)
{
@@ -328,7 +328,7 @@ public class Party
* @param player
* @param msg
*/
public void broadcastToPartyMembers(PlayerInstance player, GameServerPacket msg)
public void broadcastToPartyMembers(PlayerInstance player, IClientOutgoingPacket msg)
{
for (PlayerInstance member : _members)
{

View File

@@ -19,7 +19,7 @@ package org.l2jmobius.gameserver.model;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.clientpackets.GameClientPacket;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
@@ -34,7 +34,7 @@ public class Request
protected PlayerInstance _partner;
protected boolean _isRequestor;
protected boolean _isAnswerer;
protected GameClientPacket _requestPacket;
protected IClientIncomingPacket _requestPacket;
public Request(PlayerInstance player)
{
@@ -70,7 +70,7 @@ public class Request
* Set the packet incomed from requester.
* @param packet
*/
private synchronized void setRequestPacket(GameClientPacket packet)
private synchronized void setRequestPacket(IClientIncomingPacket packet)
{
_requestPacket = packet;
}
@@ -78,7 +78,7 @@ public class Request
/**
* @return the packet originally incomed from requester.
*/
public GameClientPacket getRequestPacket()
public IClientIncomingPacket getRequestPacket()
{
return _requestPacket;
}
@@ -89,7 +89,7 @@ public class Request
* @param packet
* @return
*/
public synchronized boolean setRequest(PlayerInstance partner, GameClientPacket packet)
public synchronized boolean setRequest(PlayerInstance partner, IClientIncomingPacket packet)
{
if (partner == null)
{

View File

@@ -115,7 +115,7 @@ import org.l2jmobius.gameserver.network.serverpackets.ChangeMoveType;
import org.l2jmobius.gameserver.network.serverpackets.ChangeWaitType;
import org.l2jmobius.gameserver.network.serverpackets.CharMoveToLocation;
import org.l2jmobius.gameserver.network.serverpackets.ExOlympiadSpelledInfo;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.MagicEffectIcons;
import org.l2jmobius.gameserver.network.serverpackets.MagicSkillCanceld;
import org.l2jmobius.gameserver.network.serverpackets.MagicSkillLaunched;
@@ -368,7 +368,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
getAttackByList().add(creature);
}
public void broadcastPacket(GameServerPacket mov)
public void broadcastPacket(IClientOutgoingPacket mov)
{
for (PlayerInstance player : getKnownList().getKnownPlayers().values())
{
@@ -376,7 +376,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
}
}
public void broadcastPacket(GameServerPacket mov, int radius)
public void broadcastPacket(IClientOutgoingPacket mov, int radius)
{
for (PlayerInstance player : getKnownList().getKnownPlayers().values())
{
@@ -509,7 +509,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
* <li>PlayerInstance</li><br>
* @param mov the mov
*/
public void sendPacket(GameServerPacket mov)
public void sendPacket(IClientOutgoingPacket mov)
{
// default implementation
}

View File

@@ -526,7 +526,7 @@ public class DoorInstance extends Creature
// Send a Server->Client packet MyTargetSelected to the PlayerInstance player
player.sendPacket(new MyTargetSelected(getObjectId(), 0));
player.sendPacket(new DoorStatusUpdate(this));
player.sendPacket(new DoorStatusUpdate(this, player));
// Send a Server->Client packet ValidateLocation to correct the NpcInstance position and heading on the client
player.sendPacket(new ValidateLocation(this));
@@ -577,7 +577,7 @@ public class DoorInstance extends Creature
player.sendPacket(new MyTargetSelected(getObjectId(), player.getLevel()));
if (isAutoAttackable(player))
{
player.sendPacket(new DoorStatusUpdate(this));
player.sendPacket(new DoorStatusUpdate(this, player));
}
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
final StringBuilder html1 = new StringBuilder("<html><body><center><font color=\"LEVEL\">Door Information</font></center>");
@@ -603,7 +603,7 @@ public class DoorInstance extends Creature
player.sendPacket(new MyTargetSelected(getObjectId(), player.getLevel()));
if (isAutoAttackable(player))
{
player.sendPacket(new DoorStatusUpdate(this));
player.sendPacket(new DoorStatusUpdate(this, player));
}
final NpcHtmlMessage reply = new NpcHtmlMessage(5);
@@ -627,10 +627,9 @@ public class DoorInstance extends Creature
return;
}
final DoorStatusUpdate su = new DoorStatusUpdate(this);
for (PlayerInstance player : knownPlayers)
{
player.sendPacket(su);
player.sendPacket(new DoorStatusUpdate(this, player));
}
}

View File

@@ -189,8 +189,8 @@ import org.l2jmobius.gameserver.network.serverpackets.ExOlympiadUserInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExPCCafePointInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExSetCompassZoneCode;
import org.l2jmobius.gameserver.network.serverpackets.FriendList;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.HennaInfo;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
import org.l2jmobius.gameserver.network.serverpackets.ItemList;
import org.l2jmobius.gameserver.network.serverpackets.LeaveWorld;
@@ -2141,7 +2141,7 @@ public class PlayerInstance extends Playable
_curWeightPenalty = 0;
super.removeSkill(getKnownSkill(4270));
sendPacket(new EtcStatusUpdate(this));
Broadcast.toKnownPlayers(this, new CharInfo(this));
Broadcast.toKnownPlayers(this, new CharInfo(this, isGM() && getAppearance().isInvisible()));
}
else
{
@@ -2186,7 +2186,7 @@ public class PlayerInstance extends Playable
}
sendPacket(new EtcStatusUpdate(this));
Broadcast.toKnownPlayers(this, new CharInfo(this));
Broadcast.toKnownPlayers(this, new CharInfo(this, isGM() && getAppearance().isInvisible()));
}
}
}
@@ -4966,7 +4966,36 @@ public class PlayerInstance extends Playable
{
// Send a Server->Client packet UserInfo to this PlayerInstance
sendPacket(new UserInfo(this));
Broadcast.toKnownPlayers(this, new CharInfo(this));
// Broadcast char info to known players
broadcastCharInfo();
}
public void broadcastCharInfo()
{
final CharInfo charInfo = new CharInfo(this, false);
for (PlayerInstance player : getKnownList().getKnownPlayers().values())
{
if (player == null)
{
continue;
}
try
{
if (player.isGM() && getAppearance().isInvisible())
{
player.sendPacket(new CharInfo(this, true));
}
else
{
player.sendPacket(charInfo);
}
}
catch (NullPointerException e)
{
}
}
}
/**
@@ -4980,7 +5009,7 @@ public class PlayerInstance extends Playable
}
@Override
public void broadcastPacket(GameServerPacket mov)
public void broadcastPacket(IClientOutgoingPacket mov)
{
final boolean isCharInfo = mov instanceof CharInfo;
if (!isCharInfo)
@@ -5009,7 +5038,7 @@ public class PlayerInstance extends Playable
}
@Override
public void broadcastPacket(GameServerPacket mov, int radius)
public void broadcastPacket(IClientOutgoingPacket mov, int radius)
{
final boolean isCharInfo = mov instanceof CharInfo;
if (!isCharInfo)
@@ -6344,8 +6373,8 @@ public class PlayerInstance extends Playable
// Anti FARM same IP
if (Config.ANTI_FARM_IP_ENABLED && (_client != null) && (targetPlayer.getClient() != null))
{
final String ip1 = _client.getConnection().getInetAddress().getHostAddress();
final String ip2 = targetPlayer.getClient().getConnection().getInetAddress().getHostAddress();
final String ip1 = _client.getConnectionAddress().getHostAddress();
final String ip2 = targetPlayer.getClient().getConnectionAddress().getHostAddress();
if (ip1.equals(ip2))
{
sendMessage("Farm is punishable with Ban! GM informed.");
@@ -6365,9 +6394,9 @@ public class PlayerInstance extends Playable
private void addItemReward(PlayerInstance targetPlayer)
{
// IP check
if ((targetPlayer.getClient() != null) && (targetPlayer.getClient().getConnection() != null))
if ((targetPlayer.getClient() != null) && (targetPlayer.getClient().getConnectionAddress() != null))
{
if (targetPlayer.getClient().getConnection().getInetAddress() != _client.getConnection().getInetAddress())
if (targetPlayer.getClient().getConnectionAddress() != _client.getConnectionAddress())
{
if ((targetPlayer.getKarma() > 0) || (targetPlayer.getPvpFlag() > 0)) // killing target pk or in pvp
{
@@ -10047,7 +10076,7 @@ public class PlayerInstance extends Playable
}
// Pk protection config
if (Config.ALLOW_CHAR_KILL_PROTECT && skill.isOffensive() && !isGM() && (target.isPlayer()) && (target.getActingPlayer().getPvpFlag() == 0) && (target.getActingPlayer().getKarma() == 0))
if (Config.ALLOW_CHAR_KILL_PROTECT && skill.isOffensive() && !isGM() && target.isPlayer() && (target.getActingPlayer().getPvpFlag() == 0) && (target.getActingPlayer().getKarma() == 0))
{
final int thisLevel = getLevel();
final int targetLevel = target.getActingPlayer().getLevel();
@@ -11413,7 +11442,7 @@ public class PlayerInstance extends Playable
* Send a Server->Client packet StatusUpdate to the PlayerInstance.
*/
@Override
public void sendPacket(GameServerPacket packet)
public void sendPacket(IClientOutgoingPacket packet)
{
if (_client != null)
{
@@ -15253,12 +15282,12 @@ public class PlayerInstance extends Playable
boolean canMultiBox = true;
int boxCount = 1;
final List<String> activeBoxes = new ArrayList<>();
if ((_client != null) && (_client.getConnection() != null) && !_client.getConnection().isClosed() && (_client.getConnection().getInetAddress() != null))
if ((_client != null) && (_client.getConnectionAddress() != null) && !_client.isDetached() && (_client.getConnectionAddress() != null))
{
final String playerIP = _client.getConnection().getInetAddress().getHostAddress();
final String playerIP = _client.getConnectionAddress().getHostAddress();
for (PlayerInstance player : World.getInstance().getAllPlayers())
{
if ((player != null) && (player != this) && player.isOnline() && (player.getClient() != null) && (player.getClient().getConnection() != null) && !player.getClient().getConnection().isClosed() && (player.getClient().getConnection().getInetAddress() != null) && playerIP.equals(player.getClient().getConnection().getInetAddress().getHostAddress()))
if ((player != null) && (player != this) && player.isOnline() && (player.getClient() != null) && (player.getClient().getConnectionAddress() != null) && !player.getClient().isDetached() && (player.getClient().getConnectionAddress() != null) && playerIP.equals(player.getClient().getConnectionAddress().getHostAddress()))
{
boxCount++;
activeBoxes.add(player.getName());
@@ -15290,12 +15319,12 @@ public class PlayerInstance extends Playable
*/
public void refreshOtherBoxes()
{
if ((_client != null) && (_client.getConnection() != null) && !_client.getConnection().isClosed() && (_client.getConnection().getInetAddress() != null))
if ((_client != null) && (_client.getConnectionAddress() != null) && !_client.isDetached() && (_client.getConnectionAddress() != null))
{
final String playerIP = _client.getConnection().getInetAddress().getHostAddress();
final String playerIP = _client.getConnectionAddress().getHostAddress();
for (PlayerInstance player : World.getInstance().getAllPlayers())
{
if ((player != null) && (player != this) && player.isOnline() && (player.getClient() != null) && (player.getClient().getConnection() != null) && !player.getClient().getConnection().isClosed() && !player.getName().equals(getName()) && playerIP.equals(player.getClient().getConnection().getInetAddress().getHostAddress()))
if ((player != null) && (player != this) && player.isOnline() && (player.getClient() != null) && (player.getClient().getConnectionAddress() != null) && !player.getClient().isDetached() && !player.getName().equals(getName()) && playerIP.equals(player.getClient().getConnectionAddress().getHostAddress()))
{
player._activeBoxes = _activeBoxes;
player._activeBoxCharacters = _activeBoxCharacters;

View File

@@ -139,7 +139,7 @@ public class PlayerKnownList extends PlayableKnownList
{
activeChar.sendPacket(new DoorInfo((DoorInstance) object, false));
}
activeChar.sendPacket(new DoorStatusUpdate((DoorInstance) object));
activeChar.sendPacket(new DoorStatusUpdate((DoorInstance) object, activeChar));
}
else if (object.isBoat())
{
@@ -180,7 +180,7 @@ public class PlayerKnownList extends PlayableKnownList
if (otherPlayer.isInBoat())
{
otherPlayer.getPosition().setWorldPosition(otherPlayer.getBoat().getLocation());
activeChar.sendPacket(new CharInfo(otherPlayer));
activeChar.sendPacket(new CharInfo(otherPlayer, activeChar.isGM() && otherPlayer.getAppearance().isInvisible()));
final int relation = otherPlayer.getRelation(activeChar);
if ((otherPlayer.getKnownList().getKnownRelations().get(activeChar.getObjectId()) != null) && (otherPlayer.getKnownList().getKnownRelations().get(activeChar.getObjectId()) != relation))
@@ -192,7 +192,7 @@ public class PlayerKnownList extends PlayableKnownList
}
else
{
activeChar.sendPacket(new CharInfo(otherPlayer));
activeChar.sendPacket(new CharInfo(otherPlayer, activeChar.isGM() && otherPlayer.getAppearance().isInvisible()));
final int relation = otherPlayer.getRelation(activeChar);
if ((otherPlayer.getKnownList().getKnownRelations().get(activeChar.getObjectId()) != null) && (otherPlayer.getKnownList().getKnownRelations().get(activeChar.getObjectId()) != relation))

View File

@@ -46,7 +46,7 @@ import org.l2jmobius.gameserver.model.itemcontainer.ItemContainer;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.ItemList;
import org.l2jmobius.gameserver.network.serverpackets.PledgeReceiveSubPledgeCreated;
import org.l2jmobius.gameserver.network.serverpackets.PledgeShowInfoUpdate;
@@ -1142,7 +1142,7 @@ public class Clan
}
}
public void broadcastToOnlineAllyMembers(GameServerPacket packet)
public void broadcastToOnlineAllyMembers(IClientOutgoingPacket packet)
{
if (_allyId == 0)
{
@@ -1158,7 +1158,7 @@ public class Clan
}
}
public void broadcastToOnlineMembers(GameServerPacket packet)
public void broadcastToOnlineMembers(IClientOutgoingPacket packet)
{
for (ClanMember member : _members.values())
{
@@ -1176,7 +1176,7 @@ public class Clan
}
}
public void broadcastToOtherOnlineMembers(GameServerPacket packet, PlayerInstance player)
public void broadcastToOtherOnlineMembers(IClientOutgoingPacket packet, PlayerInstance player)
{
for (ClanMember member : _members.values())
{

View File

@@ -46,8 +46,8 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.FortressSiegeInfo;
import org.l2jmobius.gameserver.network.serverpackets.RelationChanged;
import org.l2jmobius.gameserver.network.serverpackets.SiegeInfo;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
@@ -784,7 +784,7 @@ public class FortSiege
*/
public void listRegisterClan(PlayerInstance player)
{
player.sendPacket(new FortressSiegeInfo(getFort()));
player.sendPacket(new SiegeInfo(getFort(), player));
}
/**

View File

@@ -951,7 +951,7 @@ public class Siege
*/
public void listRegisterClan(PlayerInstance player)
{
player.sendPacket(new SiegeInfo(getCastle()));
player.sendPacket(new SiegeInfo(getCastle(), player));
}
/**

View File

@@ -23,7 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
/**
* Abstract base class for any zone type Handles basic operations
@@ -331,7 +331,7 @@ public abstract class ZoneType
* Broadcasts packet to all players inside the zone
* @param packet
*/
public void broadcastPacket(GameServerPacket packet)
public void broadcastPacket(IClientOutgoingPacket packet)
{
if (_characterList.isEmpty())
{

View File

@@ -0,0 +1,50 @@
/*
* 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 org.l2jmobius.gameserver.network;
import java.nio.ByteOrder;
import org.l2jmobius.commons.network.codecs.CryptCodec;
import org.l2jmobius.commons.network.codecs.LengthFieldBasedFrameEncoder;
import org.l2jmobius.commons.network.codecs.PacketDecoder;
import org.l2jmobius.commons.network.codecs.PacketEncoder;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
/**
* @author Nos
*/
public class ClientInitializer extends ChannelInitializer<SocketChannel>
{
private static final LengthFieldBasedFrameEncoder LENGTH_ENCODER = new LengthFieldBasedFrameEncoder();
private static final PacketEncoder PACKET_ENCODER = new PacketEncoder(0x8000 - 2);
@Override
protected void initChannel(SocketChannel ch)
{
final GameClient client = new GameClient();
ch.pipeline().addLast("length-decoder", new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 0x8000 - 2, 0, 2, -2, 2, false));
ch.pipeline().addLast("length-encoder", LENGTH_ENCODER);
ch.pipeline().addLast("crypt-codec", new CryptCodec(client.getCrypt()));
// ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
ch.pipeline().addLast("packet-decoder", new PacketDecoder<>(IncomingPackets.PACKET_ARRAY, client));
ch.pipeline().addLast("packet-encoder", PACKET_ENCODER);
ch.pipeline().addLast(client);
}
}

View File

@@ -14,48 +14,28 @@
* 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 org.l2jmobius.commons.mmocore;
package org.l2jmobius.gameserver.network;
import java.nio.BufferOverflowException;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.NetworkManager;
/**
* @author Forsaiken
* @author Nos
*/
public class NioNetStringBuffer
public class ClientNetworkManager extends NetworkManager
{
private final char[] _buf;
private final int _size;
private int _len;
public NioNetStringBuffer(int size)
protected ClientNetworkManager()
{
_buf = new char[size];
_size = size;
_len = 0;
super(EventLoopGroupManager.getInstance().getBossGroup(), EventLoopGroupManager.getInstance().getWorkerGroup(), new ClientInitializer(), Config.GAMESERVER_HOSTNAME, Config.PORT_GAME);
}
public void clear()
public static ClientNetworkManager getInstance()
{
_len = 0;
return SingletonHolder.INSTANCE;
}
public void append(char c)
private static class SingletonHolder
{
if (_len < _size)
{
_buf[_len++] = c;
}
else
{
throw new BufferOverflowException();
}
protected static final ClientNetworkManager INSTANCE = new ClientNetworkManager();
}
@Override
public String toString()
{
return new String(_buf, 0, _len);
}
}
}

View File

@@ -16,13 +16,23 @@
*/
package org.l2jmobius.gameserver.network;
import org.l2jmobius.commons.network.IConnectionState;
/**
* @author KenM
*/
public enum ConnectionState
public enum ConnectionState implements IConnectionState
{
CONNECTED,
DISCONNECTED,
CLOSING,
AUTHENTICATED,
ENTERING,
IN_GAME
IN_GAME;
public static final ConnectionState[] ENTERING_AND_IN_GAME = new ConnectionState[]
{
ConnectionState.ENTERING,
ConnectionState.IN_GAME
};
}

View File

@@ -0,0 +1,117 @@
/*
* 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 org.l2jmobius.gameserver.network;
import org.l2jmobius.commons.network.ICrypt;
import io.netty.buffer.ByteBuf;
/**
* @author UnAfraid, Nos
*/
public class Crypt implements ICrypt
{
// private final GameClient _client;
private final byte[] _inKey = new byte[16];
private final byte[] _outKey = new byte[16];
private boolean _isEnabled;
public Crypt(GameClient client)
{
// _client = client;
}
public void setKey(byte[] key)
{
System.arraycopy(key, 0, _inKey, 0, 16);
System.arraycopy(key, 0, _outKey, 0, 16);
}
@Override
public void encrypt(ByteBuf buf)
{
if (!_isEnabled)
{
_isEnabled = true;
onPacketSent(buf);
return;
}
onPacketSent(buf);
int a = 0;
while (buf.isReadable())
{
final int b = buf.readByte() & 0xFF;
a = b ^ _outKey[(buf.readerIndex() - 1) & 15] ^ a;
buf.setByte(buf.readerIndex() - 1, a);
}
shiftKey(_outKey, buf.writerIndex());
}
@Override
public void decrypt(ByteBuf buf)
{
if (!_isEnabled)
{
onPacketReceive(buf);
return;
}
int a = 0;
while (buf.isReadable())
{
final int b = buf.readByte() & 0xFF;
buf.setByte(buf.readerIndex() - 1, b ^ _inKey[(buf.readerIndex() - 1) & 15] ^ a);
a = b;
}
shiftKey(_inKey, buf.writerIndex());
onPacketReceive(buf);
}
private void onPacketSent(ByteBuf buf)
{
final byte[] data = new byte[buf.writerIndex()];
buf.getBytes(0, data);
// EventDispatcher.getInstance().notifyEvent(new OnPacketSent(_client, data));
}
private void onPacketReceive(ByteBuf buf)
{
final byte[] data = new byte[buf.writerIndex()];
buf.getBytes(0, data);
// EventDispatcher.getInstance().notifyEvent(new OnPacketReceived(_client, data));
}
private void shiftKey(byte[] key, int size)
{
int old = key[8] & 0xff;
old |= (key[9] << 8) & 0xff00;
old |= (key[10] << 0x10) & 0xff0000;
old |= (key[11] << 0x18) & 0xff000000;
old += size;
key[8] = (byte) (old & 0xff);
key[9] = (byte) ((old >> 0x08) & 0xff);
key[10] = (byte) ((old >> 0x10) & 0xff);
key[11] = (byte) ((old >> 0x18) & 0xff);
}
}

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 org.l2jmobius.gameserver.network;
import org.l2jmobius.Config;
import io.netty.channel.nio.NioEventLoopGroup;
/**
* @author Nos
*/
public class EventLoopGroupManager
{
private final NioEventLoopGroup _bossGroup = new NioEventLoopGroup(1);
private final NioEventLoopGroup _workerGroup = new NioEventLoopGroup(Config.IO_PACKET_THREAD_CORE_SIZE);
public NioEventLoopGroup getBossGroup()
{
return _bossGroup;
}
public NioEventLoopGroup getWorkerGroup()
{
return _workerGroup;
}
public void shutdown()
{
_bossGroup.shutdownGracefully();
_workerGroup.shutdownGracefully();
}
public static EventLoopGroupManager getInstance()
{
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder
{
protected static final EventLoopGroupManager INSTANCE = new EventLoopGroupManager();
}
}

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 org.l2jmobius.gameserver.network;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
import org.l2jmobius.commons.network.IConnectionState;
import org.l2jmobius.commons.network.IIncomingPacket;
import org.l2jmobius.commons.network.IIncomingPackets;
import org.l2jmobius.gameserver.network.clientpackets.AnswerJoinPartyRoom;
import org.l2jmobius.gameserver.network.clientpackets.RequestAskJoinPartyRoom;
import org.l2jmobius.gameserver.network.clientpackets.RequestAutoSoulShot;
import org.l2jmobius.gameserver.network.clientpackets.RequestChangePartyLeader;
import org.l2jmobius.gameserver.network.clientpackets.RequestConfirmCancelItem;
import org.l2jmobius.gameserver.network.clientpackets.RequestConfirmGemStone;
import org.l2jmobius.gameserver.network.clientpackets.RequestConfirmRefinerItem;
import org.l2jmobius.gameserver.network.clientpackets.RequestConfirmTargetItem;
import org.l2jmobius.gameserver.network.clientpackets.RequestCursedWeaponList;
import org.l2jmobius.gameserver.network.clientpackets.RequestCursedWeaponLocation;
import org.l2jmobius.gameserver.network.clientpackets.RequestDismissPartyRoom;
import org.l2jmobius.gameserver.network.clientpackets.RequestDuelAnswerStart;
import org.l2jmobius.gameserver.network.clientpackets.RequestDuelStart;
import org.l2jmobius.gameserver.network.clientpackets.RequestDuelSurrender;
import org.l2jmobius.gameserver.network.clientpackets.RequestExAcceptJoinMPCC;
import org.l2jmobius.gameserver.network.clientpackets.RequestExAskJoinMPCC;
import org.l2jmobius.gameserver.network.clientpackets.RequestExEnchantSkill;
import org.l2jmobius.gameserver.network.clientpackets.RequestExEnchantSkillInfo;
import org.l2jmobius.gameserver.network.clientpackets.RequestExFishRanking;
import org.l2jmobius.gameserver.network.clientpackets.RequestExMPCCShowPartyMembersInfo;
import org.l2jmobius.gameserver.network.clientpackets.RequestExMagicSkillUseGround;
import org.l2jmobius.gameserver.network.clientpackets.RequestExOustFromMPCC;
import org.l2jmobius.gameserver.network.clientpackets.RequestExPledgeCrestLarge;
import org.l2jmobius.gameserver.network.clientpackets.RequestExSetPledgeCrestLarge;
import org.l2jmobius.gameserver.network.clientpackets.RequestExitPartyMatchingWaitingRoom;
import org.l2jmobius.gameserver.network.clientpackets.RequestGetBossRecord;
import org.l2jmobius.gameserver.network.clientpackets.RequestListPartyMatchingWaitingRoom;
import org.l2jmobius.gameserver.network.clientpackets.RequestManorList;
import org.l2jmobius.gameserver.network.clientpackets.RequestOlympiadMatchList;
import org.l2jmobius.gameserver.network.clientpackets.RequestOlympiadObserverEnd;
import org.l2jmobius.gameserver.network.clientpackets.RequestOustFromPartyRoom;
import org.l2jmobius.gameserver.network.clientpackets.RequestPCCafeCouponUse;
import org.l2jmobius.gameserver.network.clientpackets.RequestPledgeMemberInfo;
import org.l2jmobius.gameserver.network.clientpackets.RequestPledgeMemberPowerInfo;
import org.l2jmobius.gameserver.network.clientpackets.RequestPledgePowerGradeList;
import org.l2jmobius.gameserver.network.clientpackets.RequestPledgeReorganizeMember;
import org.l2jmobius.gameserver.network.clientpackets.RequestPledgeSetAcademyMaster;
import org.l2jmobius.gameserver.network.clientpackets.RequestPledgeSetMemberPowerGrade;
import org.l2jmobius.gameserver.network.clientpackets.RequestPledgeWarList;
import org.l2jmobius.gameserver.network.clientpackets.RequestProcureCropList;
import org.l2jmobius.gameserver.network.clientpackets.RequestRefine;
import org.l2jmobius.gameserver.network.clientpackets.RequestRefineCancel;
import org.l2jmobius.gameserver.network.clientpackets.RequestSetCrop;
import org.l2jmobius.gameserver.network.clientpackets.RequestSetSeed;
import org.l2jmobius.gameserver.network.clientpackets.RequestWithdrawPartyRoom;
import org.l2jmobius.gameserver.network.clientpackets.RequestWriteHeroWords;
/**
* @author Mobius
*/
public enum ExIncomingPackets implements IIncomingPackets<GameClient>
{
REQUEST_OUST_FROM_PARTY_ROOM(0x01, RequestOustFromPartyRoom::new, ConnectionState.IN_GAME),
REQUEST_DISMISS_PARTY_ROOM(0x02, RequestDismissPartyRoom::new, ConnectionState.IN_GAME),
REQUEST_WITHDRAW_PARTY_ROOM(0x03, RequestWithdrawPartyRoom::new, ConnectionState.IN_GAME),
REQUEST_CHANGE_PARTY_LEADER(0x04, RequestChangePartyLeader::new, ConnectionState.IN_GAME),
REQUEST_AUTO_SOUL_SHOT(0x05, RequestAutoSoulShot::new, ConnectionState.IN_GAME),
REQUEST_EX_ENCHANT_SKILL_INFO(0x06, RequestExEnchantSkillInfo::new, ConnectionState.IN_GAME),
REQUEST_EX_ENCHANT_SKILL(0x07, RequestExEnchantSkill::new, ConnectionState.IN_GAME),
REQUEST_MANOR_LIST(0x08, RequestManorList::new, ConnectionState.IN_GAME),
REQUEST_PROCURE_CROP_LIST(0x09, RequestProcureCropList::new, ConnectionState.IN_GAME),
REQUEST_SET_SEED(0x0A, RequestSetSeed::new, ConnectionState.IN_GAME),
REQUEST_SET_CROP(0x0B, RequestSetCrop::new, ConnectionState.IN_GAME),
REQUEST_WRITE_HERO_WORDS(0x0C, RequestWriteHeroWords::new, ConnectionState.IN_GAME),
REQUEST_EX_ASK_JOIN_MPCC(0x0D, RequestExAskJoinMPCC::new, ConnectionState.IN_GAME),
REQUEST_EX_ACCEPT_JOIN_MPCC(0x0E, RequestExAcceptJoinMPCC::new, ConnectionState.IN_GAME),
REQUEST_EX_OUST_FROM_MPCC(0x0F, RequestExOustFromMPCC::new, ConnectionState.IN_GAME),
REQUEST_EX_PLEDGE_CREST_LARGE(0x10, RequestExPledgeCrestLarge::new, ConnectionState.IN_GAME),
REQUEST_EX_SET_PLEDGE_CREST_LARGE(0x11, RequestExSetPledgeCrestLarge::new, ConnectionState.IN_GAME),
REQUEST_OLYMPIAD_OBSERVER_END(0x12, RequestOlympiadObserverEnd::new, ConnectionState.IN_GAME),
REQUEST_OLYMPIAD_MATCH_LIST(0x13, RequestOlympiadMatchList::new, ConnectionState.IN_GAME),
REQUEST_ASK_JOIN_PARTY_ROOM(0x14, RequestAskJoinPartyRoom::new, ConnectionState.IN_GAME),
ANSWER_JOIN_PARTY_ROOM(0x15, AnswerJoinPartyRoom::new, ConnectionState.IN_GAME),
REQUEST_LIST_PARTY_MATCHING_WAITING_ROOM(0x16, RequestListPartyMatchingWaitingRoom::new, ConnectionState.IN_GAME),
REQUEST_EXIT_PARTY_MATCHING_WAITING_ROOM(0x17, RequestExitPartyMatchingWaitingRoom::new, ConnectionState.IN_GAME),
REQUEST_GET_BOSS_RECORD(0x18, RequestGetBossRecord::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SET_ACADEMY_MASTER(0x19, RequestPledgeSetAcademyMaster::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_POWER_GRADE_LIST(0x1A, RequestPledgePowerGradeList::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_MEMBER_POWER_INFO(0x1B, RequestPledgeMemberPowerInfo::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SET_MEMBER_POWER_GRADE(0x1C, RequestPledgeSetMemberPowerGrade::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_MEMBER_INFO(0x1D, RequestPledgeMemberInfo::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_WAR_LIST(0x1E, RequestPledgeWarList::new, ConnectionState.IN_GAME),
REQUEST_EX_FISH_RANKING(0x1F, RequestExFishRanking::new, ConnectionState.IN_GAME),
REQUEST_PC_CAFE_COUPON_USE(0x20, RequestPCCafeCouponUse::new, ConnectionState.IN_GAME),
REQUEST_CURSED_WEAPON_LIST(0x21, RequestCursedWeaponList::new, ConnectionState.IN_GAME),
REQUEST_CURSED_WEAPON_LOCATION(0x23, RequestCursedWeaponLocation::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_REORGANIZE_MEMBER(0x24, RequestPledgeReorganizeMember::new, ConnectionState.IN_GAME),
REQUEST_EX_MPCC_SHOW_PARTY_MEMBERS_INFO(0x25, RequestExMPCCShowPartyMembersInfo::new, ConnectionState.IN_GAME),
REQUEST_DUEL_START(0x27, RequestDuelStart::new, ConnectionState.IN_GAME),
REQUEST_DUEL_ANSWER_START(0x28, RequestDuelAnswerStart::new, ConnectionState.IN_GAME),
REQUEST_CONFIRM_TARGET_ITEM(0x29, RequestConfirmTargetItem::new, ConnectionState.IN_GAME),
REQUEST_CONFIRM_REFINER_ITEM(0x2A, RequestConfirmRefinerItem::new, ConnectionState.IN_GAME),
REQUEST_CONFIRM_GEM_STONE(0x2B, RequestConfirmGemStone::new, ConnectionState.IN_GAME),
REQUEST_REFINE(0x2C, RequestRefine::new, ConnectionState.IN_GAME),
REQUEST_CONFIRM_CANCEL_ITEM(0x2D, RequestConfirmCancelItem::new, ConnectionState.IN_GAME),
REQUEST_REFINE_CANCEL(0x2E, RequestRefineCancel::new, ConnectionState.IN_GAME),
REQUEST_EX_MAGIC_SKILL_USE_GROUND(0x2F, RequestExMagicSkillUseGround::new, ConnectionState.IN_GAME),
REQUEST_DUEL_SURRENDER(0x30, RequestDuelSurrender::new, ConnectionState.IN_GAME);
public static final ExIncomingPackets[] PACKET_ARRAY;
static
{
final short maxPacketId = (short) Arrays.stream(values()).mapToInt(IIncomingPackets::getPacketId).max().orElse(0);
PACKET_ARRAY = new ExIncomingPackets[maxPacketId + 1];
for (ExIncomingPackets incomingPacket : values())
{
PACKET_ARRAY[incomingPacket.getPacketId()] = incomingPacket;
}
}
private int _packetId;
private Supplier<IIncomingPacket<GameClient>> _incomingPacketFactory;
private Set<IConnectionState> _connectionStates;
ExIncomingPackets(int packetId, Supplier<IIncomingPacket<GameClient>> incomingPacketFactory, IConnectionState... connectionStates)
{
// packetId is an unsigned short
if (packetId > 0xFFFF)
{
throw new IllegalArgumentException("packetId must not be bigger than 0xFFFF");
}
_packetId = packetId;
_incomingPacketFactory = incomingPacketFactory != null ? incomingPacketFactory : () -> null;
_connectionStates = new HashSet<>(Arrays.asList(connectionStates));
}
@Override
public int getPacketId()
{
return _packetId;
}
@Override
public IIncomingPacket<GameClient> newIncomingPacket()
{
return _incomingPacketFactory.get();
}
@Override
public Set<IConnectionState> getConnectionStates()
{
return _connectionStates;
}
}

View File

@@ -17,25 +17,25 @@
package org.l2jmobius.gameserver.network;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.net.InetSocketAddress;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.mmocore.MMOClient;
import org.l2jmobius.commons.mmocore.MMOConnection;
import org.l2jmobius.commons.mmocore.ReceivablePacket;
import org.l2jmobius.commons.network.ChannelInboundHandler;
import org.l2jmobius.commons.network.ICrypt;
import org.l2jmobius.commons.network.IIncomingPacket;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.LoginServerThread;
import org.l2jmobius.gameserver.LoginServerThread.SessionKey;
@@ -53,37 +53,125 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import org.l2jmobius.gameserver.network.serverpackets.LeaveWorld;
import org.l2jmobius.gameserver.network.serverpackets.ServerClose;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.util.EventData;
import org.l2jmobius.gameserver.util.FloodProtectors;
public class GameClient extends MMOClient<MMOConnection<GameClient>> implements Runnable
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
/**
* Represents a client connected on Game Server.
* @author KenM
*/
public class GameClient extends ChannelInboundHandler<GameClient>
{
protected static final Logger LOGGER = Logger.getLogger(GameClient.class.getName());
protected static final Logger LOGGER_ACCOUNTING = Logger.getLogger("accounting");
private final FloodProtectors _floodProtectors = new FloodProtectors(this);
private final ReentrantLock _playerLock = new ReentrantLock();
private final List<Integer> _charSlotMapping = new ArrayList<>();
private final ReentrantLock _queueLock = new ReentrantLock();
private final ArrayBlockingQueue<ReceivablePacket<GameClient>> _packetQueue;
private final GameCrypt _crypt;
private ConnectionState _state;
private final Crypt _crypt;
private InetAddress _addr;
private Channel _channel;
private String _accountName;
private SessionKey _sessionId;
private ScheduledFuture<?> _cleanupTask = null;
private PlayerInstance _player;
private final List<Integer> _charSlotMapping = new ArrayList<>();
private volatile boolean _isDetached = false;
private boolean _isAuthedGG;
private int _protocolVersion;
protected PlayerInstance _player;
private ScheduledFuture<?> _cleanupTask = null;
public GameClient(MMOConnection<GameClient> con)
public GameClient()
{
super(con);
_state = ConnectionState.CONNECTED;
_crypt = new GameCrypt();
_packetQueue = new ArrayBlockingQueue<>(Config.CLIENT_PACKET_QUEUE_SIZE);
_crypt = new Crypt(this);
}
@Override
public void channelActive(ChannelHandlerContext ctx)
{
super.channelActive(ctx);
setConnectionState(ConnectionState.CONNECTED);
final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
_addr = address.getAddress();
_channel = ctx.channel();
LOGGER_ACCOUNTING.finer("Client Connected: " + ctx.channel());
}
@Override
public void channelInactive(ChannelHandlerContext ctx)
{
LOGGER_ACCOUNTING.finer("Client Disconnected: " + ctx.channel());
LoginServerThread.getInstance().sendLogout(getAccountName());
if ((_player == null) || !_player.isInOfflineMode())
{
// no long running tasks here, do it async
try
{
ThreadPool.execute(new DisconnectTask());
}
catch (RejectedExecutionException e)
{
// server is closing
}
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, IIncomingPacket<GameClient> packet)
{
try
{
packet.run(this);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Exception for: " + toString() + " on packet.run: " + packet.getClass().getSimpleName(), e);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
{
}
public void closeNow()
{
if (_channel != null)
{
_channel.close();
}
synchronized (this)
{
if (_cleanupTask != null)
{
cancelCleanup();
}
_cleanupTask = ThreadPool.schedule(new CleanupTask(), 0); // delayed?
}
}
public void close(IClientOutgoingPacket packet)
{
sendPacket(packet);
closeNow();
}
public void close(boolean toLoginScreen)
{
close(toLoginScreen ? ServerClose.STATIC_PACKET : LeaveWorld.STATIC_PACKET);
}
public Channel getChannel()
{
return _channel;
}
public byte[] enableCrypt()
@@ -93,33 +181,13 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
return key;
}
public ConnectionState getState()
/**
* For loaded offline traders returns localhost address.
* @return cached connection IP address, for checking detached clients.
*/
public InetAddress getConnectionAddress()
{
return _state;
}
public void setState(ConnectionState pState)
{
if (_state != pState)
{
_state = pState;
_packetQueue.clear();
}
}
@Override
public boolean decrypt(ByteBuffer buf, int size)
{
_crypt.decrypt(buf.array(), buf.position(), size);
return true;
}
@Override
public boolean encrypt(ByteBuffer buf, int size)
{
_crypt.encrypt(buf.array(), buf.position(), size);
buf.position(buf.position() + size);
return true;
return _addr;
}
public PlayerInstance getPlayer()
@@ -141,16 +209,16 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
return _playerLock;
}
public boolean isAuthedGG()
{
return _isAuthedGG;
}
public void setGameGuardOk(boolean value)
{
_isAuthedGG = value;
}
public boolean isAuthedGG()
{
return _isAuthedGG;
}
public void setAccountName(String pAccountName)
{
_accountName = pAccountName;
@@ -171,18 +239,26 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
return _sessionId;
}
public void sendPacket(GameServerPacket gsp)
public void sendPacket(IClientOutgoingPacket packet)
{
if (_isDetached)
if (_isDetached || (packet == null))
{
return;
}
if (getConnection() != null)
{
getConnection().sendPacket(gsp);
gsp.runImpl();
}
// Write into the channel.
_channel.writeAndFlush(packet);
// Run packet implementation.
packet.runImpl(_player);
}
/**
* @param smId
*/
public void sendPacket(SystemMessageId smId)
{
sendPacket(new SystemMessage(smId));
}
public boolean isDetached()
@@ -197,17 +273,17 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
/**
* Method to handle character deletion
* @param charslot
* @param characterSlot
* @return a byte:
* <li>-1: Error: No char was found for such charslot, caught exception, etc...
* <li>0: character is not member of any clan, proceed with deletion
* <li>1: character is member of a clan, but not clan leader
* <li>2: character is clan leader
*/
public byte markToDeleteChar(int charslot)
public byte markToDeleteChar(int characterSlot)
{
final int objid = getObjectIdForSlot(charslot);
if (objid < 0)
final int objectId = getObjectIdForSlot(characterSlot);
if (objectId < 0)
{
return -1;
}
@@ -217,7 +293,7 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
try (Connection con = DatabaseFactory.getConnection())
{
PreparedStatement statement = con.prepareStatement("SELECT clanId from characters WHERE charId=?");
statement.setInt(1, objid);
statement.setInt(1, objectId);
final ResultSet rs = statement.executeQuery();
rs.next();
@@ -230,7 +306,7 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
{
answer = 0; // jeezes!
}
else if (clan.getLeaderId() == objid)
else if (clan.getLeaderId() == objectId)
{
answer = 2;
}
@@ -245,13 +321,13 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
{
if (Config.DELETE_DAYS == 0)
{
deleteCharByObjId(objid);
deleteCharByObjId(objectId);
}
else
{
statement = con.prepareStatement("UPDATE characters SET deletetime=? WHERE charId=?");
statement.setLong(1, Chronos.currentTimeMillis() + (Config.DELETE_DAYS * 86400000)); // 24*60*60*1000 = 86400000
statement.setInt(2, objid);
statement.setInt(2, objectId);
statement.execute();
statement.close();
rs.close();
@@ -272,11 +348,11 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
return answer;
}
public void markRestoredChar(int charslot)
public void markRestoredChar(int characterSlot)
{
// have to make sure active character must be nulled
final int objid = getObjectIdForSlot(charslot);
if (objid < 0)
final int objectId = getObjectIdForSlot(characterSlot);
if (objectId < 0)
{
return;
}
@@ -284,7 +360,7 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
try (Connection con = DatabaseFactory.getConnection())
{
final PreparedStatement statement = con.prepareStatement("UPDATE characters SET deletetime=0 WHERE charId=?");
statement.setInt(1, objid);
statement.setInt(1, objectId);
statement.execute();
statement.close();
}
@@ -294,102 +370,102 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
}
}
public static void deleteCharByObjId(int objid)
public static void deleteCharByObjId(int objectId)
{
if (objid < 0)
if (objectId < 0)
{
return;
}
try (Connection con = DatabaseFactory.getConnection())
{
PreparedStatement statement;
PreparedStatement ps;
statement = con.prepareStatement("DELETE FROM character_friends WHERE char_id=? OR friend_id=?");
statement.setInt(1, objid);
statement.setInt(2, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_friends WHERE char_id=? OR friend_id=?");
ps.setInt(1, objectId);
ps.setInt(2, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_hennas WHERE char_obj_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_macroses WHERE char_obj_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_macroses WHERE char_obj_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_quests WHERE char_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_quests WHERE char_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_recipebook WHERE char_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_recipebook WHERE char_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE char_obj_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_shortcuts WHERE char_obj_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_skills WHERE char_obj_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_skills_save WHERE char_obj_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM character_subclasses WHERE char_obj_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM character_subclasses WHERE char_obj_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM heroes WHERE charId=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM heroes WHERE charId=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM olympiad_nobles WHERE charId=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM olympiad_nobles WHERE charId=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM seven_signs WHERE char_obj_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM seven_signs WHERE char_obj_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM pets WHERE item_obj_id IN (SELECT object_id FROM items WHERE items.owner_id=?)");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM pets WHERE item_obj_id IN (SELECT object_id FROM items WHERE items.owner_id=?)");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM augmentations WHERE item_id IN (SELECT object_id FROM items WHERE items.owner_id=?)");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM augmentations WHERE item_id IN (SELECT object_id FROM items WHERE items.owner_id=?)");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM items WHERE owner_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM items WHERE owner_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM merchant_lease WHERE player_id=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM merchant_lease WHERE player_id=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
statement = con.prepareStatement("DELETE FROM characters WHERE charId=?");
statement.setInt(1, objid);
statement.execute();
statement.close();
ps = con.prepareStatement("DELETE FROM characters WHERE charId=?");
ps.setInt(1, objectId);
ps.execute();
ps.close();
}
catch (Exception e)
{
@@ -397,31 +473,31 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
}
}
public PlayerInstance loadCharFromDisk(int charslot)
public PlayerInstance loadCharFromDisk(int characterSlot)
{
final int objId = getObjectIdForSlot(charslot);
if (objId < 0)
final int objectId = getObjectIdForSlot(characterSlot);
if (objectId < 0)
{
return null;
}
PlayerInstance character = World.getInstance().getPlayer(objId);
if (character != null)
PlayerInstance player = World.getInstance().getPlayer(objectId);
if (player != null)
{
// exploit prevention, should not happens in normal way
LOGGER.warning("Attempt of double login: " + character.getName() + "(" + objId + ") " + _accountName);
LOGGER.warning("Attempt of double login: " + player.getName() + "(" + objectId + ") " + _accountName);
if (character.getClient() != null)
if (player.getClient() != null)
{
character.getClient().closeNow();
player.getClient().closeNow();
}
else
{
character.deleteMe();
player.deleteMe();
try
{
character.store();
player.store();
}
catch (Exception e2)
{
@@ -430,8 +506,8 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
}
}
character = PlayerInstance.load(objId);
return character;
player = PlayerInstance.load(objectId);
return player;
}
public void setCharSelection(CharSelectInfoPackage[] chars)
@@ -445,14 +521,6 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
}
}
public void close(GameServerPacket gsp)
{
if (getConnection() != null)
{
getConnection().close(gsp);
}
}
private int getObjectIdForSlot(int charslot)
{
if ((charslot < 0) || (charslot >= _charSlotMapping.size()))
@@ -465,55 +533,9 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
return objectId.intValue();
}
@Override
public void onForcedDisconnection()
{
// the force operation will allow to not save client position to prevent again criticals and stuck
closeNow();
}
@Override
public void onDisconnection()
{
// no long running tasks here, do it async
try
{
ThreadPool.execute(new DisconnectTask());
}
catch (RejectedExecutionException e)
{
// server is closing
}
}
/**
* Close client connection with {@link ServerClose} packet
*/
public void closeNow()
{
close(0);
}
/**
* Close client connection with {@link ServerClose} packet
* @param delay
*/
public void close(int delay)
{
close(ServerClose.STATIC_PACKET);
synchronized (this)
{
if (_cleanupTask != null)
{
cancelCleanup();
}
_cleanupTask = ThreadPool.schedule(new CleanupTask(), delay); // delayed
}
}
public String getIpAddress()
{
final InetAddress address = getConnection().getInetAddress();
final InetAddress address = _addr;
String ip;
if (address == null)
{
@@ -534,20 +556,22 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
{
try
{
switch (_state)
final InetAddress address = _addr;
final ConnectionState state = (ConnectionState) getConnectionState();
switch (state)
{
case CONNECTED:
{
return "[IP: " + getIpAddress() + "]";
return "[IP: " + (address == null ? "disconnected" : address.getHostAddress()) + "]";
}
case AUTHENTICATED:
{
return "[Account: " + _accountName + " - IP: " + getIpAddress() + "]";
return "[Account: " + _accountName + " - IP: " + (address == null ? "disconnected" : address.getHostAddress()) + "]";
}
case ENTERING:
case IN_GAME:
{
return "[Character: " + (_player == null ? "disconnected" : _player.getName()) + " - Account: " + _accountName + " - IP: " + getIpAddress() + "]";
return "[Character: " + (_player == null ? "disconnected" : _player.getName() + "[" + _player.getObjectId() + "]") + " - Account: " + _accountName + " - IP: " + (address == null ? "disconnected" : address.getHostAddress()) + "]";
}
default:
{
@@ -771,72 +795,6 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
return _isDetached;
}
/**
* Add packet to the queue and start worker thread if needed
* @param packet
*/
public void execute(ReceivablePacket<GameClient> packet)
{
if (!_packetQueue.offer(packet))
{
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (_queueLock.isLocked())
{
return;
}
try
{
ThreadPool.execute(this);
}
catch (RejectedExecutionException e)
{
}
}
@Override
public void run()
{
if (!_queueLock.tryLock())
{
return;
}
try
{
while (true)
{
final ReceivablePacket<GameClient> packet = _packetQueue.poll();
if (packet == null)
{
return;
}
if (_isDetached) // clear queue immediately after detach
{
_packetQueue.clear();
return;
}
try
{
packet.run();
}
catch (Exception e)
{
LOGGER.warning("Exception during execution " + packet.getClass().getSimpleName() + ", client: " + this + "," + e.getMessage());
}
}
}
finally
{
_queueLock.unlock();
}
}
public void setProtocolVersion(int version)
{
_protocolVersion = version;
@@ -846,4 +804,9 @@ public class GameClient extends MMOClient<MMOConnection<GameClient>> implements
{
return _protocolVersion;
}
public ICrypt getCrypt()
{
return _crypt;
}
}

View File

@@ -1,90 +0,0 @@
/*
* 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 org.l2jmobius.gameserver.network;
/**
* @author KenM
*/
public class GameCrypt
{
private final byte[] _inKey = new byte[16];
private final byte[] _outKey = new byte[16];
private boolean _isEnabled;
public void setKey(byte[] key)
{
System.arraycopy(key, 0, _inKey, 0, 16);
System.arraycopy(key, 0, _outKey, 0, 16);
}
public void decrypt(byte[] raw, int offset, 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 & 15] ^ temp);
temp = temp2;
}
int old = _inKey[8] & 0xff;
old |= (_inKey[9] << 8) & 0xff00;
old |= (_inKey[10] << 0x10) & 0xff0000;
old |= (_inKey[11] << 0x18) & 0xff000000;
old += size;
_inKey[8] = (byte) (old & 0xff);
_inKey[9] = (byte) ((old >> 0x08) & 0xff);
_inKey[10] = (byte) ((old >> 0x10) & 0xff);
_inKey[11] = (byte) ((old >> 0x18) & 0xff);
}
public void encrypt(byte[] raw, int offset, 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 & 15] ^ temp;
raw[offset + i] = (byte) temp;
}
int old = _outKey[8] & 0xff;
old |= (_outKey[9] << 8) & 0xff00;
old |= (_outKey[10] << 0x10) & 0xff0000;
old |= (_outKey[11] << 0x18) & 0xff000000;
old += size;
_outKey[8] = (byte) (old & 0xff);
_outKey[9] = (byte) ((old >> 0x08) & 0xff);
_outKey[10] = (byte) ((old >> 0x10) & 0xff);
_outKey[11] = (byte) ((old >> 0x18) & 0xff);
}
}

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 org.l2jmobius.gameserver.network;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
import org.l2jmobius.commons.network.IConnectionState;
import org.l2jmobius.commons.network.IIncomingPacket;
import org.l2jmobius.commons.network.IIncomingPackets;
import org.l2jmobius.gameserver.network.clientpackets.*;
/**
* @author Mobius
*/
public enum IncomingPackets implements IIncomingPackets<GameClient>
{
PROTOCOL_VERSION(0x00, ProtocolVersion::new, ConnectionState.CONNECTED),
AUTH_LOGIN(0x08, AuthLogin::new, ConnectionState.CONNECTED),
LOGOUT(0x09, Logout::new, ConnectionState.AUTHENTICATED, ConnectionState.IN_GAME),
CHARACTER_CREATE(0x0B, CharacterCreate::new, ConnectionState.AUTHENTICATED),
CHARACTER_DELETE(0x0C, CharacterDelete::new, ConnectionState.AUTHENTICATED),
CHARACTER_SELECT(0x0D, CharacterSelected::new, ConnectionState.AUTHENTICATED),
NEW_CHARACTER(0x0E, NewCharacter::new, ConnectionState.AUTHENTICATED),
CHARACTER_RESTORE(0x62, CharacterRestore::new, ConnectionState.AUTHENTICATED),
REQUEST_PLEDGE_CREST(0x68, RequestPledgeCrest::new, ConnectionState.AUTHENTICATED, ConnectionState.IN_GAME),
ENTER_WORLD(0x03, EnterWorld::new, ConnectionState.ENTERING),
MOVE_BACKWARD_TO_LOCATION(0x01, MoveBackwardToLocation::new, ConnectionState.IN_GAME),
ACTION(0x04, Action::new, ConnectionState.IN_GAME),
ATTACK_REQUEST(0x0A, AttackRequest::new, ConnectionState.IN_GAME),
REQUEST_ITEM_LIST(0x0F, RequestItemList::new, ConnectionState.IN_GAME),
REQUEST_UN_EQUIP_ITEM(0x11, RequestUnEquipItem::new, ConnectionState.IN_GAME),
REQUEST_DROP_ITEM(0x12, RequestDropItem::new, ConnectionState.IN_GAME),
USE_ITEM(0x14, UseItem::new, ConnectionState.IN_GAME),
TRADE_REQUEST(0x15, TradeRequest::new, ConnectionState.IN_GAME),
ADD_TRADE_ITEM(0x16, AddTradeItem::new, ConnectionState.IN_GAME),
TRADE_DONE(0x17, TradeDone::new, ConnectionState.IN_GAME),
REQUEST_SOCIAL_ACTION(0x1B, RequestSocialAction::new, ConnectionState.IN_GAME),
CHANGE_MOVE_TYPE2(0x1C, ChangeMoveType2::new, ConnectionState.IN_GAME),
CHANGE_WAIT_TYPE2(0x1D, ChangeWaitType2::new, ConnectionState.IN_GAME),
REQUEST_SELL_ITEM(0x1E, RequestSellItem::new, ConnectionState.IN_GAME),
REQUEST_BUY_ITEM(0x1F, RequestBuyItem::new, ConnectionState.IN_GAME),
REQUEST_LINK_HTML(0x20, RequestLinkHtml::new, ConnectionState.IN_GAME),
REQUEST_BYPASS_TO_SERVER(0x21, RequestBypassToServer::new, ConnectionState.IN_GAME),
REQUEST_B_B_SWRITE(0x22, RequestBBSwrite::new, ConnectionState.IN_GAME),
REQUEST_JOIN_PLEDGE(0x24, RequestJoinPledge::new, ConnectionState.IN_GAME),
REQUEST_ANSWER_JOIN_PLEDGE(0x25, RequestAnswerJoinPledge::new, ConnectionState.IN_GAME),
REQUEST_WITHDRAWAL_PLEDGE(0x26, RequestWithdrawalPledge::new, ConnectionState.IN_GAME),
REQUEST_OUST_PLEDGE_MEMBER(0x27, RequestOustPledgeMember::new, ConnectionState.IN_GAME),
REQUEST_JOIN_PARTY(0x29, RequestJoinParty::new, ConnectionState.IN_GAME),
REQUEST_ANSWER_JOIN_PARTY(0x2A, RequestAnswerJoinParty::new, ConnectionState.IN_GAME),
REQUEST_WITH_DRAWAL_PARTY(0x2B, RequestWithDrawalParty::new, ConnectionState.IN_GAME),
REQUEST_OUST_PARTY_MEMBER(0x2C, RequestOustPartyMember::new, ConnectionState.IN_GAME),
REQUEST_MAGIC_SKILL_USE(0x2F, RequestMagicSkillUse::new, ConnectionState.IN_GAME),
APPEARING(0x30, Appearing::new, ConnectionState.IN_GAME),
SEND_WARE_HOUSE_DEPOSIT_LIST(0x31, SendWareHouseDepositList::new, ConnectionState.IN_GAME),
SEND_WARE_HOUSE_WITH_DRAW_LIST(0x32, SendWareHouseWithDrawList::new, ConnectionState.IN_GAME),
REQUEST_SHORT_CUT_REG(0x33, RequestShortCutReg::new, ConnectionState.IN_GAME),
REQUEST_SHORT_CUT_DEL(0x35, RequestShortCutDel::new, ConnectionState.IN_GAME),
CANNOT_MOVE_ANYMORE(0x36, CannotMoveAnymore::new, ConnectionState.IN_GAME),
REQUEST_TARGET_CANCELD(0x37, RequestTargetCanceld::new, ConnectionState.IN_GAME),
SAY2(0x38, Say2::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_MEMBER_LIST(0x3C, RequestPledgeMemberList::new, ConnectionState.IN_GAME),
REQUEST_SKILL_LIST(0x3F, RequestSkillList::new, ConnectionState.IN_GAME),
MOVE_WITH_DELTA(0x41, MoveWithDelta::new, ConnectionState.IN_GAME),
REQUEST_GET_ON_VEHICLE(0x42, RequestGetOnVehicle::new, ConnectionState.IN_GAME),
REQUEST_GET_OFF_VEHICLE(0x43, RequestGetOffVehicle::new, ConnectionState.IN_GAME),
ANSWER_TRADE_REQUEST(0x44, AnswerTradeRequest::new, ConnectionState.IN_GAME),
REQUEST_ACTION_USE(0x45, RequestActionUse::new, ConnectionState.IN_GAME),
REQUEST_RESTART(0x46, RequestRestart::new, ConnectionState.IN_GAME),
REQUEST_SIEGE_INFO(0x47, RequestSiegeInfo::new, ConnectionState.IN_GAME),
VALIDATE_POSITION(0x48, ValidatePosition::new, ConnectionState.IN_GAME),
START_ROTATING(0x4A, StartRotating::new, ConnectionState.IN_GAME),
FINISH_ROTATING(0x4B, FinishRotating::new, ConnectionState.IN_GAME),
REQUEST_START_PLEDGE_WAR(0x4D, RequestStartPledgeWar::new, ConnectionState.IN_GAME),
REQUEST_REPLY_START_PLEDGE_WAR(0x4E, RequestReplyStartPledgeWar::new, ConnectionState.IN_GAME),
REQUEST_STOP_PLEDGE_WAR(0x4F, RequestStopPledgeWar::new, ConnectionState.IN_GAME),
REQUEST_REPLY_STOP_PLEDGE_WAR(0x50, RequestReplyStopPledgeWar::new, ConnectionState.IN_GAME),
REQUEST_SURRENDER_PLEDGE_WAR(0x51, RequestSurrenderPledgeWar::new, ConnectionState.IN_GAME),
REQUEST_REPLY_SURRENDER_PLEDGE_WAR(0x52, RequestReplySurrenderPledgeWar::new, ConnectionState.IN_GAME),
REQUEST_SET_PLEDGE_CREST(0x53, RequestSetPledgeCrest::new, ConnectionState.IN_GAME),
REQUEST_GIVE_NICK_NAME(0x55, RequestGiveNickName::new, ConnectionState.IN_GAME),
REQUEST_SHOW_BOARD(0x57, RequestShowBoard::new, ConnectionState.IN_GAME),
REQUEST_ENCHANT_ITEM(0x58, RequestEnchantItem::new, ConnectionState.IN_GAME),
REQUEST_DESTROY_ITEM(0x59, RequestDestroyItem::new, ConnectionState.IN_GAME),
SEND_BYPASS_BUILD_CMD(0x5B, SendBypassBuildCmd::new, ConnectionState.IN_GAME),
REQUEST_MOVE_TO_LOCATION_IN_VEHICLE(0x5C, RequestMoveToLocationInVehicle::new, ConnectionState.IN_GAME),
CANNOT_MOVE_ANYMORE_IN_VEHICLE(0x5D, CannotMoveAnymoreInVehicle::new, ConnectionState.IN_GAME),
REQUEST_FRIEND_INVITE(0x5E, RequestFriendInvite::new, ConnectionState.IN_GAME),
REQUEST_ANSWER_FRIEND_INVITE(0x5F, RequestAnswerFriendInvite::new, ConnectionState.IN_GAME),
REQUEST_FRIEND_LIST(0x60, RequestFriendList::new, ConnectionState.IN_GAME),
REQUEST_FRIEND_DEL(0x61, RequestFriendDel::new, ConnectionState.IN_GAME),
REQUEST_QUEST_LIST(0x63, RequestQuestList::new, ConnectionState.IN_GAME),
REQUEST_QUEST_ABORT(0x64, RequestQuestAbort::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_INFO(0x66, RequestPledgeInfo::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_EXTENDED_INFO(0x67, RequestPledgeExtendedInfo::new, ConnectionState.IN_GAME),
REQUEST_SURRENDER_PERSONALLY(0x69, RequestSurrenderPersonally::new, ConnectionState.IN_GAME),
REQUEST_AQUIRE_SKILL_INFO(0x6B, RequestAquireSkillInfo::new, ConnectionState.IN_GAME),
REQUEST_AQUIRE_SKILL(0x6C, RequestAquireSkill::new, ConnectionState.IN_GAME),
REQUEST_RESTART_POINT(0x6D, RequestRestartPoint::new, ConnectionState.IN_GAME),
REQUEST_G_M_COMMAND(0x6E, RequestGMCommand::new, ConnectionState.IN_GAME),
REQUEST_PARTY_MATCH_CONFIG(0x6F, RequestPartyMatchConfig::new, ConnectionState.IN_GAME),
REQUEST_PARTY_MATCH_LIST(0x70, RequestPartyMatchList::new, ConnectionState.IN_GAME),
REQUEST_PARTY_MATCH_DETAIL(0x71, RequestPartyMatchDetail::new, ConnectionState.IN_GAME),
REQUEST_CRYSTALLIZE_ITEM(0x72, RequestCrystallizeItem::new, ConnectionState.IN_GAME),
REQUEST_PRIVATE_STORE_MANAGE_SELL(0x73, RequestPrivateStoreManageSell::new, ConnectionState.IN_GAME),
SET_PRIVATE_STORE_LIST_SELL(0x74, SetPrivateStoreListSell::new, ConnectionState.IN_GAME),
REQUEST_PRIVATE_STORE_QUIT_SELL(0x76, RequestPrivateStoreQuitSell::new, ConnectionState.IN_GAME),
SET_PRIVATE_STORE_MSG_SELL(0x77, SetPrivateStoreMsgSell::new, ConnectionState.IN_GAME),
REQUEST_PRIVATE_STORE_BUY(0x79, RequestPrivateStoreBuy::new, ConnectionState.IN_GAME),
REQUEST_TUTORIAL_LINK_HTML(0x7B, RequestTutorialLinkHtml::new, ConnectionState.IN_GAME),
REQUEST_TUTORIAL_PASS_CMD_TO_SERVER(0x7C, RequestTutorialPassCmdToServer::new, ConnectionState.IN_GAME),
REQUEST_TUTORIAL_QUESTION_MARK(0x7D, RequestTutorialQuestionMark::new, ConnectionState.IN_GAME),
REQUEST_TUTORIAL_CLIENT_EVENT(0x7E, RequestTutorialClientEvent::new, ConnectionState.IN_GAME),
REQUEST_PETITION(0x7F, RequestPetition::new, ConnectionState.IN_GAME),
REQUEST_PETITION_CANCEL(0x80, RequestPetitionCancel::new, ConnectionState.IN_GAME),
REQUEST_GM_LIST(0x81, RequestGmList::new, ConnectionState.IN_GAME),
REQUEST_JOIN_ALLY(0x82, RequestJoinAlly::new, ConnectionState.IN_GAME),
REQUEST_ANSWER_JOIN_ALLY(0x83, RequestAnswerJoinAlly::new, ConnectionState.IN_GAME),
ALLY_LEAVE(0x84, AllyLeave::new, ConnectionState.IN_GAME),
ALLY_DISMISS(0x85, AllyDismiss::new, ConnectionState.IN_GAME),
REQUEST_DISMISS_ALLY(0x86, RequestDismissAlly::new, ConnectionState.IN_GAME),
REQUEST_SET_ALLY_CREST(0x87, RequestSetAllyCrest::new, ConnectionState.IN_GAME),
REQUEST_ALLY_CREST(0x88, RequestAllyCrest::new, ConnectionState.IN_GAME),
REQUEST_CHANGE_PET_NAME(0x89, RequestChangePetName::new, ConnectionState.IN_GAME),
REQUEST_PET_USE_ITEM(0x8A, RequestPetUseItem::new, ConnectionState.IN_GAME),
REQUEST_GIVE_ITEM_TO_PET(0x8B, RequestGiveItemToPet::new, ConnectionState.IN_GAME),
REQUEST_GET_ITEM_FROM_PET(0x8C, RequestGetItemFromPet::new, ConnectionState.IN_GAME),
REQUEST_ALLY_INFO(0x8E, RequestAllyInfo::new, ConnectionState.IN_GAME),
REQUEST_PET_GET_ITEM(0x8F, RequestPetGetItem::new, ConnectionState.IN_GAME),
REQUEST_PRIVATE_STORE_MANAGE_BUY(0x90, RequestPrivateStoreManageBuy::new, ConnectionState.IN_GAME),
SET_PRIVATE_STORE_LIST_BUY(0x91, SetPrivateStoreListBuy::new, ConnectionState.IN_GAME),
REQUEST_PRIVATE_STORE_QUIT_BUY(0x93, RequestPrivateStoreQuitBuy::new, ConnectionState.IN_GAME),
SET_PRIVATE_STORE_MSG_BUY(0x94, SetPrivateStoreMsgBuy::new, ConnectionState.IN_GAME),
REQUEST_PRIVATE_STORE_SELL(0x96, RequestPrivateStoreSell::new, ConnectionState.IN_GAME),
REQUEST_SKILL_COOL_TIME(0x9D, RequestSkillCoolTime::new, ConnectionState.IN_GAME),
REQUEST_PACKAGE_SENDABLE_ITEM_LIST(0x9E, RequestPackageSendableItemList::new, ConnectionState.IN_GAME),
REQUEST_PACKAGE_SEND(0x9F, RequestPackageSend::new, ConnectionState.IN_GAME),
REQUEST_BLOCK(0xA0, RequestBlock::new, ConnectionState.IN_GAME),
REQUEST_SIEGE_ATTACKER_LIST(0xA2, RequestSiegeAttackerList::new, ConnectionState.IN_GAME),
REQUEST_SIEGE_DEFENDER_LIST(0xA3, RequestSiegeDefenderList::new, ConnectionState.IN_GAME),
REQUEST_JOIN_SIEGE(0xA4, RequestJoinSiege::new, ConnectionState.IN_GAME),
REQUEST_CONFIRM_SIEGE_WAITING_LIST(0xA5, RequestConfirmSiegeWaitingList::new, ConnectionState.IN_GAME),
MULTI_SELL_CHOOSE(0xA7, MultiSellChoose::new, ConnectionState.IN_GAME),
REQUEST_USER_COMMAND(0xAA, RequestUserCommand::new, ConnectionState.IN_GAME),
SNOOP_QUIT(0xAB, SnoopQuit::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_BOOK_OPEN(0xAC, RequestRecipeBookOpen::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_BOOK_DESTROY(0xAD, RequestRecipeBookDestroy::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_ITEM_MAKE_INFO(0xAE, RequestRecipeItemMakeInfo::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_ITEM_MAKE_SELF(0xAF, RequestRecipeItemMakeSelf::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_SHOP_MESSAGE_SET(0xB1, RequestRecipeShopMessageSet::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_SHOP_LIST_SET(0xB2, RequestRecipeShopListSet::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_SHOP_MANAGE_QUIT(0xB3, RequestRecipeShopManageQuit::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_SHOP_MAKE_INFO(0xB5, RequestRecipeShopMakeInfo::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_SHOP_MAKE_ITEM(0xB6, RequestRecipeShopMakeItem::new, ConnectionState.IN_GAME),
REQUEST_RECIPE_SHOP_MANAGE_PREV(0xB7, RequestRecipeShopManagePrev::new, ConnectionState.IN_GAME),
OBSERVER_RETURN(0xB8, ObserverReturn::new, ConnectionState.IN_GAME),
REQUEST_EVALUATE(0xB9, RequestEvaluate::new, ConnectionState.IN_GAME),
REQUEST_HENNA_LIST(0xBA, RequestHennaList::new, ConnectionState.IN_GAME),
REQUEST_HENNA_ITEM_INFO(0xBB, RequestHennaItemInfo::new, ConnectionState.IN_GAME),
REQUEST_HENNA_EQUIP(0xBC, RequestHennaEquip::new, ConnectionState.IN_GAME),
REQUEST_HENNA_REMOVE_LIST(0xBD, RequestHennaRemoveList::new, ConnectionState.IN_GAME),
REQUEST_HENNA_ITEM_REMOVE_INFO(0xBE, RequestHennaItemRemoveInfo::new, ConnectionState.IN_GAME),
REQUEST_HENNA_REMOVE(0xBF, RequestHennaRemove::new, ConnectionState.IN_GAME),
REQUEST_PLEDGE_POWER(0xC0, RequestPledgePower::new, ConnectionState.IN_GAME),
REQUEST_MAKE_MACRO(0xC1, RequestMakeMacro::new, ConnectionState.IN_GAME),
REQUEST_DELETE_MACRO(0xC2, RequestDeleteMacro::new, ConnectionState.IN_GAME),
REQUEST_BUY_PROCURE(0xC3, RequestBuyProcure::new, ConnectionState.IN_GAME),
REQUEST_BUY_SEED(0xC4, RequestBuySeed::new, ConnectionState.IN_GAME),
DLG_ANSWER(0xC5, DlgAnswer::new, ConnectionState.IN_GAME),
REQUEST_WEAR_ITEM(0xC6, RequestWearItem::new, ConnectionState.IN_GAME),
REQUEST_S_S_Q_STATUS(0xC7, RequestSSQStatus::new, ConnectionState.IN_GAME),
GAME_GUARD_REPLY(0xCA, GameGuardReply::new, ConnectionState.IN_GAME),
REQUEST_SEND_FRIEND_MSG(0xCC, RequestSendFriendMsg::new, ConnectionState.IN_GAME),
REQUEST_SHOW_MINI_MAP(0xCD, RequestShowMiniMap::new, ConnectionState.IN_GAME),
REQUEST_RECORD_INFO(0xCF, RequestRecordInfo::new, ConnectionState.IN_GAME),
EX_PACKET(0xD0, ExPacket::new, ConnectionState.values()); // This packet has its own connection state checking so we allow all of them
public static final IncomingPackets[] PACKET_ARRAY;
static
{
final short maxPacketId = (short) Arrays.stream(values()).mapToInt(IIncomingPackets::getPacketId).max().orElse(0);
PACKET_ARRAY = new IncomingPackets[maxPacketId + 1];
for (IncomingPackets incomingPacket : values())
{
PACKET_ARRAY[incomingPacket.getPacketId()] = incomingPacket;
}
}
private short _packetId;
private Supplier<IIncomingPacket<GameClient>> _incomingPacketFactory;
private Set<IConnectionState> _connectionStates;
IncomingPackets(int packetId, Supplier<IIncomingPacket<GameClient>> incomingPacketFactory, IConnectionState... connectionStates)
{
// packetId is an unsigned byte
if (packetId > 0xFF)
{
throw new IllegalArgumentException("packetId must not be bigger than 0xFF");
}
_packetId = (short) packetId;
_incomingPacketFactory = incomingPacketFactory != null ? incomingPacketFactory : () -> null;
_connectionStates = new HashSet<>(Arrays.asList(connectionStates));
}
@Override
public int getPacketId()
{
return _packetId;
}
@Override
public IIncomingPacket<GameClient> newIncomingPacket()
{
return _incomingPacketFactory.get();
}
@Override
public Set<IConnectionState> getConnectionStates()
{
return _connectionStates;
}
}

View File

@@ -0,0 +1,331 @@
/*
* 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 org.l2jmobius.gameserver.network;
import org.l2jmobius.commons.network.PacketWriter;
/**
* @author Mobius
*/
public enum OutgoingPackets
{
// Packets
KEY_PACKET(0x00),
CHAR_MOVE_TO_LOCATION(0x01),
CHAR_INFO(0x03),
USER_INFO(0x04),
ATTACK(0x05),
DIE(0x06),
REVIVE(0x07),
SPAWN_ITEM(0x0B),
DROP_ITEM(0x0C),
GET_ITEM(0x0D),
STATUS_UPDATE(0x0E),
NPC_HTML_MESSAGE(0x0F),
SELL_LIST(0x10),
BUY_LIST(0x11),
DELETE_OBJECT(0x12),
CHAR_SELECT_INFO(0x13),
AUTH_LOGIN_FAIL(0x14),
CHAR_SELECTED(0x15),
NPC_INFO(0x16),
CHAR_TEMPLATES(0x17),
CHAR_CREATE_OK(0x19),
CHAR_CREATE_FAIL(0x1A),
ITEM_LIST(0x1B),
SUN_RISE(0x1C),
SUN_SET(0x1D),
TRADE_START(0x1E),
TRADE_OWN_ADD(0x20),
TRADE_OTHER_ADD(0x21),
SEND_TRADE_DONE(0x22),
CHAR_DELETE_OK(0x23),
CHAR_DELETE_FAIL(0x24),
ACTION_FAILED(0x25),
SERVER_CLOSE(0x26),
INVENTORY_UPDATE(0x27),
TELEPORT_TO_LOCATION(0x28),
TARGET_SELECTED(0x29),
TARGET_UNSELECTED(0x2A),
AUTO_ATTACK_START(0x2B),
AUTO_ATTACK_STOP(0x2C),
SOCIAL_ACTION(0x2D),
CHANGE_MOVE_TYPE(0x2E),
CHANGE_WAIT_TYPE(0x2F),
MANAGE_PLEDGE_POWER(0x30),
ASK_JOIN_PLEDGE(0x32),
JOIN_PLEDGE(0x33),
ASK_JOIN_PARTY(0x39),
JOIN_PARTY(0x3A),
WARE_HOUSE_DEPOSIT_LIST(0x41),
WARE_HOUSE_WITHDRAWAL_LIST(0x42),
SHORT_CUT_REGISTER(0x44),
SHORT_CUT_INIT(0x45),
STOP_MOVE(0x47),
MAGIC_SKILL_USE(0x48),
MAGIC_SKILL_CANCELD(0x49),
CREATURE_SAY(0x4A),
EQUIP_UPDATE(0x4B),
DOOR_INFO(0x4C),
DOOR_STATUS_UPDATE(0x4D),
PARTY_SMALL_WINDOW_ALL(0x4E),
PARTY_SMALL_WINDOW_ADD(0x4F),
PARTY_SMALL_WINDOW_DELETE_ALL(0x50),
PARTY_SMALL_WINDOW_DELETE(0x51),
PARTY_SMALL_WINDOW_UPDATE(0x52),
PLEDGE_SHOW_MEMBER_LIST_ALL(0x53),
PLEDGE_SHOW_MEMBER_LIST_UPDATE(0x54),
PLEDGE_SHOW_MEMBER_LIST_ADD(0x55),
PLEDGE_SHOW_MEMBER_LIST_DELETE(0x56),
SKILL_LIST(0x58),
VEHICLE_INFO(0x59),
VEHICLE_DEPARTURE(0x5A),
ON_VEHICLE_CHECK_LOCATION(0x5B),
GET_ON_VEHICLE(0x5C),
GET_OFF_VEHICLE(0x5D),
SEND_TRADE_REQUEST(0x5E),
RESTART_RESPONSE(0x5F),
MOVE_TO_PAWN(0x60),
VALIDATE_LOCATION(0x61),
BEGIN_ROTATION(0x62),
STOP_ROTATION(0x63),
SYSTEM_MESSAGE(0x64),
START_PLEDGE_WAR(0x65),
STOP_PLEDGE_WAR(0x67),
SURRENDER_PLEDGE_WAR(0x69),
PLEDGE_CREST(0x6C),
SETUP_GAUGE(0x6D),
SHOW_BOARD(0x6E),
CHOOSE_INVENTORY_ITEM(0x6F),
MOVE_TO_LOCATION_IN_VEHICLE(0x71),
STOP_MOVE_IN_VEHICLE(0x72),
VALIDATE_LOCATION_IN_VEHICLE(0x73),
TRADE_UPDATE(0x74),
TRADE_PRESS_OWN_OK(0x75),
MAGIC_SKILL_LAUNCHED(0x76),
TRADE_PRESS_OTHER_OK(0x7C),
ASK_JOIN_FRIEND(0x7D),
LEAVE_WORLD(0x7E),
MAGIC_EFFECT_ICONS(0x7F),
QUEST_LIST(0x80),
ENCHANT_RESULT(0x81),
PLEDGE_SHOW_MEMBER_LIST_DELETE_ALL(0x82),
PLEDGE_INFO(0x83),
RIDE(0x86),
PLEDGE_SHOW_INFO_UPDATE(0x88),
AQUIRE_SKILL_LIST(0x8A),
AQUIRE_SKILL_INFO(0x8B),
GM_VIEW_CHARACTER_INFO(0x8F),
GM_VIEW_PLEDGE_INFO(0x90),
GM_VIEW_SKILL_INFO(0x91),
GM_VIEW_QUEST_LIST(0x93),
GM_VIEW_ITEM_LIST(0x94),
GM_VIEW_WAREHOUSE_WITHDRAW_LIST(0x95),
PARTY_MATCH_LIST(0x96),
PARTY_MATCH_DETAIL(0x97),
PLAY_SOUND(0x98),
STATIC_OBJECT(0x99),
PRIVATE_STORE_MANAGE_LIST_SELL(0x9A),
PRIVATE_STORE_LIST_SELL(0x9B),
PRIVATE_STORE_MSG_SELL(0x9C),
SHOW_MINI_MAP(0x9D),
TUTORIAL_SHOW_HTML(0xA0),
TUTORIAL_SHOW_QUESTION_MARK(0xA1),
TUTORIAL_ENABLE_CLIENT_EVENT(0xA2),
TUTORIAL_CLOSE_HTML(0xA3),
MY_TARGET_SELECTED(0xA6),
PARTY_MEMBER_POSITION(0xA7),
ASK_JOIN_ALLY(0xA8),
ALLY_CREST(0xAE),
PET_STATUS_SHOW(0xB0),
PET_INFO(0xB1),
PET_ITEM_LIST(0xB2),
PET_INVENTORY_UPDATE(0xB3),
PET_STATUS_UPDATE(0xB5),
PET_DELETE(0xB6),
PRIVATE_STORE_MANAGE_LIST_BUY(0xB7),
PRIVATE_STORE_LIST_BUY(0xB8),
PRIVATE_STORE_MSG_BUY(0xB9),
SKILL_COOL_TIME(0xC1),
PACKAGE_TO_LIST(0xC2),
PACKAGE_SENDABLE_LIST(0xC3),
EARTHQUAKE(0xC4),
SPECIAL_CAMERA(0xC7),
NORMAL_CAMERA(0xC8),
SIEGE_INFO(0xC9),
SIEGE_ATTACKER_LIST(0xCA),
SIEGE_DEFENDER_LIST(0xCB),
TITLE_UPDATE(0xCC),
PLEDGE_STATUS_CHANGED(0xCD),
RELATION_CHANGED(0xCE),
MULTI_SELL_LIST(0xD0),
SET_SUMMON_REMAIN_TIME(0xD1),
DICE(0xD4),
SNOOP(0xD5),
RECIPE_BOOK_ITEM_LIST(0xD6),
RECIPE_ITEM_MAKE_INFO(0xD7),
RECIPE_SHOP_MANAGE_LIST(0xD8),
RECIPE_SHOP_SELL_LIST(0xD9),
RECIPE_SHOP_ITEM_INFO(0xDA),
RECIPE_SHOP_MSG(0xDB),
SHOW_CALCULATOR(0xDC),
MON_RACE_INFO(0xDD),
SHOW_TOWN_MAP(0xDE),
OBSERVATION_MODE(0xDF),
OBSERVATION_RETURN(0xE0),
CHAIR_SIT(0xE1),
HENNA_EQUIP_LIST(0xE2),
HENNA_ITEM_INFO(0xE3),
HENNA_INFO(0xE4),
HENNA_REMOVE_LIST(0xE5),
HENNA_ITEM_REMOVE_INFO(0xE6),
SEND_MACRO_LIST(0xE7),
BUY_LIST_SEED(0xE8),
SELL_LIST_PROCURE(0xE9),
GM_VIEW_HENNA_INFO(0xEA),
RADAR_CONTROL(0xEB),
CLIENT_SET_TIME(0xEC),
CONFIRM_DLG(0xED),
PARTY_SPELLED(0xEE),
WEAR_LIST(0xEF),
CAMERA_MODE(0xF1),
SHOW_XMAS_SEAL(0xF2),
ETC_STATUS_UPDATE(0xF3),
SHORT_BUFF_STATUS_UPDATE(0xF4),
SSQ_STATUS(0xF5),
CLAN_HALL_DECORATION(0xF7),
SIGNS_SKY(0xF8),
GAME_GUARD_QUERY(0xF9),
FRIEND_LIST(0xFA),
FRIEND_RECV_MSG(0xFD),
// ExPackets
EX_COLOSSEUM_FENCE_INFO(0xFE, 0x09),
EX_PARTY_ROOM_MEMBER(0xFE, 0x0E),
EX_CLOSE_PARTY_ROOM(0xFE, 0x0F),
EX_MANAGE_PARTY_ROOM_MEMBER(0xFE, 0x10),
EX_AUTO_SOUL_SHOT(0xFE, 0x12),
EX_FISHING_START(0xFE, 0x13),
EX_FISHING_END(0xFE, 0x14),
EX_FISHING_START_COMBAT(0xFE, 0x15),
EX_FISHING_HP_REGEN(0xFE, 0x16),
EX_ENCHANT_SKILL_LIST(0xFE, 0x17),
EX_ENCHANT_SKILL_INFO(0xFE, 0x18),
EX_QUEST_INFO(0xFE, 0x19),
EX_SHOW_QUEST_MARK(0xFE, 0x1A),
EX_SEND_MANOR_LIST(0xFE, 0x1B),
EX_SHOW_SEED_INFO(0xFE, 0x1C),
EX_SHOW_CROP_INFO(0xFE, 0x1D),
EX_SHOW_MANOR_DEFAULT_INFO(0xFE, 0x1E),
EX_SHOW_SEED_SETTING(0xFE, 0x1F),
EX_SHOW_CROP_SETTING(0xFE, 0x20),
EX_SHOW_SELL_CROP_LIST(0xFE, 0x21),
EX_SHOW_PROCURE_CROP_DETAIL(0xFE, 0x22),
EX_HERO_LIST(0xFE, 0x23),
EX_SERVER_PRIMITIVE(0xFE, 0x24),
EX_OPEN_MPCC(0xFE, 0x25),
EX_CLOSE_MPCC(0xFE, 0x26),
EX_ASK_JOIN_MPCC(0xFE, 0x27),
EX_PLEDGE_CREST_LARGE(0xFE, 0x28),
EX_OLYMPIAD_USER_INFO(0xFE, 0x29),
EX_OLYMPIAD_SPELLED_INFO(0xFE, 0x2A),
EX_OLYMPIAD_MODE(0xFE, 0x2B),
EX_MAIL_ARRIVED(0xFE, 0x2D),
EX_STORAGE_MAX_COUNT(0xFE, 0x2E),
EX_MULTI_PARTY_COMMAND_CHANNEL_INFO(0xFE, 0x30),
EX_PC_CAFE_POINT_INFO(0xFE, 0x31),
EX_SET_COMPASS_ZONE_CODE(0xFE, 0x32),
EX_GET_BOSS_RECORD(0xFE, 0x33),
EX_ASK_JOIN_PARTY_ROOM(0xFE, 0x34),
EX_LIST_PARTY_MATCHING_WAITING_ROOM(0xFE, 0x35),
EX_SHOW_ADVENTURER_GUIDE_BOOK(0xFE, 0x37),
EX_SHOW_SCREEN_MESSAGE(0xFE, 0x38),
PLEDGE_SKILL_LIST(0xFE, 0x39),
PLEDGE_SKILL_LIST_ADD(0xFE, 0x3A),
PLEDGE_POWER_GRADE_LIST(0xFE, 0x3B),
PLEDGE_RECEIVE_POWER_INFO(0xFE, 0x3C),
PLEDGE_RECEIVE_MEMBER_INFO(0xFE, 0x3D),
PLEDGE_RECEIVE_WAR_LIST(0xFE, 0x3E),
PLEDGE_RECEIVE_SUB_PLEDGE_CREATED(0xFE, 0x3F),
EX_RED_SKY(0xFE, 0x40),
SHOW_PC_CAFE_COUPON_SHOW_UI(0xFE, 0x43),
EX_CAPTURE_ORC(0xFE, 0x44),
EX_CURSED_WEAPON_LIST(0xFE, 0x45),
EX_CURSED_WEAPON_LOCATION(0xFE, 0x46),
EX_RESTART_CLIENT(0xFE, 0x47),
EX_REQUEST_HACK_SHIELD(0xFE, 0x48),
EX_USE_SHARED_GROUP_ITEM(0xFE, 0x49),
EX_MPCC_SHOW_PARTY_MEMBER_INFO(0xFE, 0x4A),
EX_DUEL_ASK_START(0xFE, 0x4B),
EX_DUEL_READY(0xFE, 0x4C),
EX_DUEL_START(0xFE, 0x4D),
EX_DUEL_END(0xFE, 0x4E),
EX_DUEL_UPDATE_USER_INFO(0xFE, 0x4F),
EX_SHOW_VARIATION_MAKE_WINDOW(0xFE, 0x50),
EX_SHOW_VARIATION_CANCEL_WINDOW(0xFE, 0x51),
EX_CONFIRM_VARIATION_ITEM(0xFE, 0x52),
EX_CONFIRM_VARIATION_REFINER(0xFE, 0x53),
EX_CONFIRM_VARIATION_GEMSTONE(0xFE, 0x54),
EX_VARIATION_RESULT(0xFE, 0x55),
EX_CONFIRM_CANCEL_ITEM(0xFE, 0x56),
EX_VARIATION_CANCEL_RESULT(0xFE, 0x57),
EX_SHOW_SLIDESHOW_KAMAEL(0xFE, 0x5B);
private final int _id1;
private final int _id2;
OutgoingPackets(int id1)
{
this(id1, -1);
}
OutgoingPackets(int id1, int id2)
{
_id1 = id1;
_id2 = id2;
}
public int getId1()
{
return _id1;
}
public int getId2()
{
return _id2;
}
public void writeId(PacketWriter packet)
{
packet.writeC(_id1);
if (_id2 > 0)
{
packet.writeH(_id2);
}
}
public static OutgoingPackets getPacket(int id1, int id2)
{
for (OutgoingPackets packet : values())
{
if ((packet.getId1() == id1) && (packet.getId2() == id2))
{
return packet;
}
}
return null;
}
}

View File

@@ -18,38 +18,43 @@ package org.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
@SuppressWarnings("unused")
public class Action extends GameClientPacket
public class Action implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(Action.class.getName());
private int _objectId;
@SuppressWarnings("unused")
private int _originX;
@SuppressWarnings("unused")
private int _originY;
@SuppressWarnings("unused")
private int _originZ;
private int _actionId;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_objectId = readD(); // Target object Identifier
_originX = readD();
_originY = readD();
_originZ = readD();
_actionId = readC(); // Action identifier : 0-Simple click, 1-Shift click
_objectId = packet.readD(); // Target object Identifier
_originX = packet.readD();
_originY = packet.readD();
_originZ = packet.readD();
_actionId = packet.readC(); // Action identifier : 0-Simple click, 1-Shift click
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
// Get the current PlayerInstance of the player
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
@@ -76,21 +81,21 @@ public class Action extends GameClientPacket
// pressing e.g. pickup many times quickly would get you here
if (obj == null)
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Players can't interact with objects in the other instances except from multiverse
if ((obj.getInstanceId() != player.getInstanceId()) && (player.getInstanceId() != -1))
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Only GMs can directly interact with invisible characters
if ((obj instanceof PlayerInstance) && (((PlayerInstance) obj).getAppearance().isInvisible()) && !player.isGM())
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
@@ -112,7 +117,7 @@ public class Action extends GameClientPacket
}
else
{
obj.onActionShift(getClient());
obj.onActionShift(client);
}
break;
}
@@ -120,14 +125,14 @@ public class Action extends GameClientPacket
{
// Invalid action detected (probably client cheating), LOGGER this
LOGGER.warning("Character: " + player.getName() + " requested invalid action: " + _actionId);
getClient().sendPacket(ActionFailed.STATIC_PACKET);
client.sendPacket(ActionFailed.STATIC_PACKET);
break;
}
}
}
else
{
getClient().sendPacket(ActionFailed.STATIC_PACKET); // Actions prohibited when in trade
client.sendPacket(ActionFailed.STATIC_PACKET); // Actions prohibited when in trade
}
}
}

View File

@@ -18,16 +18,18 @@ package org.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.TradeList;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.TradeOtherAdd;
import org.l2jmobius.gameserver.network.serverpackets.TradeOwnAdd;
import org.l2jmobius.gameserver.network.serverpackets.TradeUpdate;
public class AddTradeItem extends GameClientPacket
public class AddTradeItem implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(AddTradeItem.class.getName());
private int _tradeId;
@@ -35,17 +37,18 @@ public class AddTradeItem extends GameClientPacket
private int _count;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_tradeId = readD();
_objectId = readD();
_count = readD();
_tradeId = packet.readD();
_objectId = packet.readD();
_count = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -17,31 +17,34 @@
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.sql.ClanTable;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
public class AllyDismiss extends GameClientPacket
public class AllyDismiss implements IClientIncomingPacket
{
private String _clanName;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_clanName = readS();
_clanName = packet.readS();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
if (_clanName == null)
{
return;
}
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -17,22 +17,25 @@
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
public class AllyLeave extends GameClientPacket
public class AllyLeave implements IClientIncomingPacket
{
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -16,31 +16,34 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.partymatching.PartyMatchRoom;
import org.l2jmobius.gameserver.model.partymatching.PartyMatchRoomList;
import org.l2jmobius.gameserver.model.partymatching.PartyMatchWaitingList;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ExManagePartyRoomMember;
import org.l2jmobius.gameserver.network.serverpackets.ExPartyRoomMember;
import org.l2jmobius.gameserver.network.serverpackets.PartyMatchDetail;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public class AnswerJoinPartyRoom extends GameClientPacket
public class AnswerJoinPartyRoom implements IClientIncomingPacket
{
private int _answer; // 1 or 0
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_answer = readD();
_answer = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -16,27 +16,30 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.SendTradeDone;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public class AnswerTradeRequest extends GameClientPacket
public class AnswerTradeRequest implements IClientIncomingPacket
{
private int _response;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_response = readD();
_response = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -16,27 +16,30 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
/**
* Appearing Packet Handler
*/
public class Appearing extends GameClientPacket
public class Appearing implements IClientIncomingPacket
{
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if ((player == null) || !player.isOnline())
{
sendPacket(ActionFailed.STATIC_PACKET);
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
@@ -45,6 +48,6 @@ public class Appearing extends GameClientPacket
player.onTeleported();
}
sendPacket(new UserInfo(player));
client.sendPacket(new UserInfo(player));
}
}

View File

@@ -16,6 +16,7 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.instancemanager.events.CTF;
import org.l2jmobius.gameserver.instancemanager.events.DM;
@@ -24,10 +25,11 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.instance.SummonInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
@SuppressWarnings("unused")
public class AttackRequest extends GameClientPacket
public class AttackRequest implements IClientIncomingPacket
{
private int _objectId;
private int _originX;
@@ -36,19 +38,20 @@ public class AttackRequest extends GameClientPacket
private int _attackId;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_objectId = readD();
_originX = readD();
_originY = readD();
_originZ = readD();
_attackId = readC(); // 0 for simple click - 1 for shift-click
_objectId = packet.readD();
_originX = packet.readD();
_originY = packet.readD();
_originZ = packet.readD();
_attackId = packet.readC(); // 0 for simple click - 1 for shift-click
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
@@ -157,7 +160,7 @@ public class AttackRequest extends GameClientPacket
}
else
{
sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
}
}
}

View File

@@ -16,11 +16,12 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.LoginServerThread;
import org.l2jmobius.gameserver.LoginServerThread.SessionKey;
import org.l2jmobius.gameserver.network.GameClient;
public class AuthLogin extends GameClientPacket
public class AuthLogin implements IClientIncomingPacket
{
// loginName + keys must match what the loginserver used.
private String _loginName;
@@ -30,20 +31,20 @@ public class AuthLogin extends GameClientPacket
private int _loginKey2;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_loginName = readS().toLowerCase();
_playKey2 = readD();
_playKey1 = readD();
_loginKey1 = readD();
_loginKey2 = readD();
_loginName = packet.readS().toLowerCase();
_playKey2 = packet.readD();
_playKey1 = packet.readD();
_loginKey1 = packet.readD();
_loginKey2 = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final SessionKey key = new SessionKey(_loginKey1, _loginKey2, _playKey1, _playKey2);
final GameClient client = getClient();
// avoid potential exploits
if (client.getAccountName() == null)

View File

@@ -16,11 +16,13 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
public class CannotMoveAnymore extends GameClientPacket
public class CannotMoveAnymore implements IClientIncomingPacket
{
private int _x;
private int _y;
@@ -28,18 +30,19 @@ public class CannotMoveAnymore extends GameClientPacket
private int _heading;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_x = readD();
_y = readD();
_z = readD();
_heading = readD();
_x = packet.readD();
_y = packet.readD();
_z = packet.readD();
_heading = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -16,14 +16,16 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.StopMoveInVehicle;
/**
* @author Maktakien
*/
public class CannotMoveAnymoreInVehicle extends GameClientPacket
public class CannotMoveAnymoreInVehicle implements IClientIncomingPacket
{
private int _x;
private int _y;
@@ -32,19 +34,20 @@ public class CannotMoveAnymoreInVehicle extends GameClientPacket
private int _boatId;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_boatId = readD();
_x = readD();
_y = readD();
_z = readD();
_heading = readD();
_boatId = packet.readD();
_x = packet.readD();
_y = packet.readD();
_z = packet.readD();
_heading = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -16,22 +16,25 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
public class ChangeMoveType2 extends GameClientPacket
public class ChangeMoveType2 implements IClientIncomingPacket
{
private boolean _typeRun;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_typeRun = readD() == 1;
_typeRun = packet.readD() == 1;
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -16,62 +16,62 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.instancemanager.CastleManager;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.instance.StaticObjectInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.ChairSit;
public class ChangeWaitType2 extends GameClientPacket
public class ChangeWaitType2 implements IClientIncomingPacket
{
private boolean _typeStand;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_typeStand = readD() == 1;
_typeStand = packet.readD() == 1;
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
}
final WorldObject target = player.getTarget();
if (getClient() != null)
if (player.isOutOfControl())
{
if (player.isOutOfControl())
{
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (player.getMountType() != 0)
{
return;
}
if ((target != null) && !player.isSitting() && (target instanceof StaticObjectInstance) && (((StaticObjectInstance) target).getType() == 1) && (CastleManager.getInstance().getCastle(target) != null) && player.isInsideRadius2D(target, StaticObjectInstance.INTERACTION_DISTANCE))
{
final ChairSit cs = new ChairSit(player, ((StaticObjectInstance) target).getStaticObjectId());
player.sendPacket(cs);
player.sitDown();
player.broadcastPacket(cs);
}
if (_typeStand)
{
player.standUp();
}
else
{
player.sitDown();
}
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (player.getMountType() != 0)
{
return;
}
if ((target != null) && !player.isSitting() && (target instanceof StaticObjectInstance) && (((StaticObjectInstance) target).getType() == 1) && (CastleManager.getInstance().getCastle(target) != null) && player.isInsideRadius2D(target, StaticObjectInstance.INTERACTION_DISTANCE))
{
final ChairSit cs = new ChairSit(player, ((StaticObjectInstance) target).getStaticObjectId());
player.sendPacket(cs);
player.sitDown();
player.broadcastPacket(cs);
}
if (_typeStand)
{
player.standUp();
}
else
{
player.sitDown();
}
}
}

View File

@@ -22,6 +22,7 @@ import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.data.ItemTable;
import org.l2jmobius.gameserver.data.SkillTable;
import org.l2jmobius.gameserver.data.sql.CharNameTable;
@@ -46,7 +47,7 @@ import org.l2jmobius.gameserver.network.serverpackets.CharCreateOk;
import org.l2jmobius.gameserver.network.serverpackets.CharSelectInfo;
import org.l2jmobius.gameserver.util.Util;
public class CharacterCreate extends GameClientPacket
public class CharacterCreate implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(CharacterCreate.class.getName());
@@ -72,29 +73,30 @@ public class CharacterCreate extends GameClientPacket
private int _wit;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_name = readS();
_race = readD();
_sex = (byte) readD();
_classId = readD();
_int = readD();
_str = readD();
_con = readD();
_men = readD();
_dex = readD();
_wit = readD();
_hairStyle = (byte) readD();
_hairColor = (byte) readD();
_face = (byte) readD();
_name = packet.readS();
_race = packet.readD();
_sex = (byte) packet.readD();
_classId = packet.readD();
_int = packet.readD();
_str = packet.readD();
_con = packet.readD();
_men = packet.readD();
_dex = packet.readD();
_wit = packet.readD();
_hairStyle = (byte) packet.readD();
_hairColor = (byte) packet.readD();
_face = (byte) packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
if ((_name.length() < 3) || (_name.length() > 16) || !Util.isAlphaNumeric(_name) || !isValidName(_name))
{
sendPacket(new CharCreateFail(CharCreateFail.REASON_16_ENG_CHARS));
client.sendPacket(new CharCreateFail(CharCreateFail.REASON_16_ENG_CHARS));
return;
}
@@ -104,7 +106,7 @@ public class CharacterCreate extends GameClientPacket
{
if (_name.toLowerCase().contains(st.toLowerCase()))
{
getClient().sendPacket(new CharCreateFail(CharCreateFail.REASON_INCORRECT_NAME));
client.sendPacket(new CharCreateFail(CharCreateFail.REASON_INCORRECT_NAME));
return;
}
}
@@ -116,26 +118,26 @@ public class CharacterCreate extends GameClientPacket
// Since checks for duplicate names are done using SQL, lock must be held until data is written to DB as well.
synchronized (CharNameTable.getInstance())
{
if ((CharNameTable.getInstance().accountCharNumber(getClient().getAccountName()) >= Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT) && (Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT != 0))
if ((CharNameTable.getInstance().accountCharNumber(client.getAccountName()) >= Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT) && (Config.MAX_CHARACTERS_NUMBER_PER_ACCOUNT != 0))
{
sendPacket(new CharCreateFail(CharCreateFail.REASON_TOO_MANY_CHARACTERS));
client.sendPacket(new CharCreateFail(CharCreateFail.REASON_TOO_MANY_CHARACTERS));
return;
}
else if (CharNameTable.getInstance().doesCharNameExist(_name))
{
sendPacket(new CharCreateFail(CharCreateFail.REASON_NAME_ALREADY_EXISTS));
client.sendPacket(new CharCreateFail(CharCreateFail.REASON_NAME_ALREADY_EXISTS));
return;
}
template = PlayerTemplateData.getInstance().getTemplate(_classId);
if ((template == null) || (template.getClassBaseLevel() > 1))
{
sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
client.sendPacket(new CharCreateFail(CharCreateFail.REASON_CREATION_FAILED));
return;
}
final int objectId = IdManager.getInstance().getNextId();
newChar = PlayerInstance.create(objectId, template, getClient().getAccountName(), _name, _hairStyle, _hairColor, _face, _sex != 0);
newChar = PlayerInstance.create(objectId, template, client.getAccountName(), _name, _hairStyle, _hairColor, _face, _sex != 0);
newChar.setCurrentHp(newChar.getMaxHp()); // L2Off like
// newChar.setCurrentCp(template.baseCpMax);
newChar.setCurrentCp(0); // L2Off like
@@ -143,8 +145,8 @@ public class CharacterCreate extends GameClientPacket
// newChar.setMaxLoad(template.baseLoad);
// send acknowledgement
sendPacket(new CharCreateOk()); // Success
initNewChar(getClient(), newChar);
client.sendPacket(new CharCreateOk()); // Success
initNewChar(client, newChar);
}
}
@@ -160,7 +162,7 @@ public class CharacterCreate extends GameClientPacket
}
catch (PatternSyntaxException e) // case of illegal pattern
{
LOGGER.warning("ERROR " + getType() + ": Character name pattern of config is wrong!");
LOGGER.warning("Character name pattern of config is wrong!");
pattern = Pattern.compile(".*");
}
@@ -297,7 +299,7 @@ public class CharacterCreate extends GameClientPacket
// Send char list
final CharSelectInfo cl = new CharSelectInfo(client.getAccountName(), client.getSessionId().playOkID1);
client.getConnection().sendPacket(cl);
client.sendPacket(cl);
client.setCharSelection(cl.getCharInfo());
}

View File

@@ -16,8 +16,11 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.CharDeleteFail;
import org.l2jmobius.gameserver.network.serverpackets.CharDeleteOk;
import org.l2jmobius.gameserver.network.serverpackets.CharSelectInfo;
@@ -25,28 +28,29 @@ import org.l2jmobius.gameserver.network.serverpackets.CharSelectInfo;
/**
* @author eX1steam
*/
public class CharacterDelete extends GameClientPacket
public class CharacterDelete implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(CharacterDelete.class.getName());
private int _charSlot;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_charSlot = readD();
_charSlot = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
if (!getClient().getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterDelete"))
if (!client.getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterDelete"))
{
return;
}
try
{
final byte answer = getClient().markToDeleteChar(_charSlot);
final byte answer = client.markToDeleteChar(_charSlot);
switch (answer)
{
default:
@@ -56,28 +60,28 @@ public class CharacterDelete extends GameClientPacket
}
case 0: // Success!
{
sendPacket(new CharDeleteOk());
client.sendPacket(new CharDeleteOk());
break;
}
case 1:
{
sendPacket(new CharDeleteFail(CharDeleteFail.REASON_YOU_MAY_NOT_DELETE_CLAN_MEMBER));
client.sendPacket(new CharDeleteFail(CharDeleteFail.REASON_YOU_MAY_NOT_DELETE_CLAN_MEMBER));
break;
}
case 2:
{
sendPacket(new CharDeleteFail(CharDeleteFail.REASON_CLAN_LEADERS_MAY_NOT_BE_DELETED));
client.sendPacket(new CharDeleteFail(CharDeleteFail.REASON_CLAN_LEADERS_MAY_NOT_BE_DELETED));
break;
}
}
}
catch (Exception e)
{
LOGGER.warning("ERROR " + getType() + ": " + e);
LOGGER.log(Level.SEVERE, "Error:", e);
}
final CharSelectInfo cl = new CharSelectInfo(getClient().getAccountName(), getClient().getSessionId().playOkID1, 0);
sendPacket(cl);
getClient().setCharSelection(cl.getCharInfo());
final CharSelectInfo cl = new CharSelectInfo(client.getAccountName(), client.getSessionId().playOkID1, 0);
client.sendPacket(cl);
client.setCharSelection(cl.getCharInfo());
}
}

View File

@@ -16,36 +16,39 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.CharSelectInfo;
public class CharacterRestore extends GameClientPacket
public class CharacterRestore implements IClientIncomingPacket
{
private int _charSlot;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_charSlot = readD();
_charSlot = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
if (!getClient().getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterRestore"))
if (!client.getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterRestore"))
{
return;
}
try
{
getClient().markRestoredChar(_charSlot);
client.markRestoredChar(_charSlot);
}
catch (Exception e)
{
}
final CharSelectInfo cl = new CharSelectInfo(getClient().getAccountName(), getClient().getSessionId().playOkID1, 0);
sendPacket(cl);
getClient().setCharSelection(cl.getCharInfo());
final CharSelectInfo cl = new CharSelectInfo(client.getAccountName(), client.getSessionId().playOkID1, 0);
client.sendPacket(cl);
client.setCharSelection(cl.getCharInfo());
}
}

View File

@@ -18,13 +18,15 @@ package org.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.ConnectionState;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.CharSelected;
@SuppressWarnings("unused")
public class CharacterSelected extends GameClientPacket
public class CharacterSelected implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(CharacterSelected.class.getName());
@@ -35,41 +37,42 @@ public class CharacterSelected extends GameClientPacket
private int _unk4;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_charSlot = readD();
_unk1 = readH();
_unk2 = readD();
_unk3 = readD();
_unk4 = readD();
_charSlot = packet.readD();
_unk1 = packet.readH();
_unk2 = packet.readD();
_unk3 = packet.readD();
_unk4 = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
// if there is a playback.dat file in the current directory, it will be sent to the client instead of any regular packets
// to make this work, the first packet in the playback.dat has to be a [S]0x21 packet
// after playback is done, the client will not work correct and need to exit
// playLogFile(getConnection()); // try to play LOGGER file
if (!getClient().getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterSelect"))
if (!client.getFloodProtectors().getCharacterSelect().tryPerformAction("CharacterSelect"))
{
return;
}
// we should always be abble to acquire the lock but if we cant lock then nothing should be done (ie repeated packet)
if (getClient().getPlayerLock().tryLock())
if (client.getPlayerLock().tryLock())
{
try
{
// should always be null but if not then this is repeated packet and nothing should be done here
if (getClient().getPlayer() == null)
if (client.getPlayer() == null)
{
// Load up character from disk
final PlayerInstance cha = getClient().loadCharFromDisk(_charSlot);
final PlayerInstance cha = client.loadCharFromDisk(_charSlot);
if (cha == null)
{
LOGGER.warning(getType() + ": Character could not be loaded (slot:" + _charSlot + ")");
sendPacket(ActionFailed.STATIC_PACKET);
LOGGER.warning("Character could not be loaded (slot:" + _charSlot + ")");
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
@@ -79,10 +82,10 @@ public class CharacterSelected extends GameClientPacket
return;
}
cha.setClient(getClient());
getClient().setPlayer(cha);
getClient().setState(ConnectionState.ENTERING);
sendPacket(new CharSelected(cha, getClient().getSessionId().playOkID1));
cha.setClient(client);
client.setPlayer(cha);
client.setConnectionState(ConnectionState.ENTERING);
client.sendPacket(new CharSelected(cha, client.getSessionId().playOkID1));
}
}
catch (Exception e)
@@ -91,7 +94,7 @@ public class CharacterSelected extends GameClientPacket
}
finally
{
getClient().getPlayerLock().unlock();
client.getPlayerLock().unlock();
}
}
}

View File

@@ -17,31 +17,34 @@
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
/**
* @author Dezmond_snz - Packet Format: cddd
*/
public class DlgAnswer extends GameClientPacket
public class DlgAnswer implements IClientIncomingPacket
{
private int _messageId;
private int _answer;
private int _requesterId;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_messageId = readD();
_answer = readD();
_requesterId = readD();
_messageId = packet.readD();
_answer = packet.readD();
_requesterId = packet.readD();
return true;
}
@Override
public void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -26,6 +26,7 @@ import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.GameTimeController;
import org.l2jmobius.gameserver.communitybbs.Manager.MailBBSManager;
@@ -68,6 +69,7 @@ import org.l2jmobius.gameserver.model.siege.FortSiege;
import org.l2jmobius.gameserver.model.siege.Siege;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.ConnectionState;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ClientSetTime;
import org.l2jmobius.gameserver.network.serverpackets.CreatureSay;
@@ -98,7 +100,7 @@ import org.l2jmobius.gameserver.util.Util;
/**
* Enter World Packet Handler
*/
public class EnterWorld extends GameClientPacket
public class EnterWorld implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(EnterWorld.class.getName());
@@ -106,23 +108,23 @@ public class EnterWorld extends GameClientPacket
SimpleDateFormat df = new SimpleDateFormat("dd MM yyyy");
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
// this is just a trigger packet. it has no content
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
LOGGER.warning("EnterWorld failed! player is null...");
getClient().closeNow();
client.closeNow();
return;
}
getClient().setState(ConnectionState.IN_GAME);
client.setConnectionState(ConnectionState.IN_GAME);
// Set lock at login
player.setLocked(true);
@@ -132,7 +134,7 @@ public class EnterWorld extends GameClientPacket
if (!player.isGM() && !player.isDonator() && Config.CHECK_NAME_ON_LOGIN && ((player.getName().length() < 3) || (player.getName().length() > 16) || !Util.isAlphaNumeric(player.getName()) || !isValidName(player.getName())))
{
LOGGER.warning("Charname: " + player.getName() + " is invalid. EnterWorld failed.");
getClient().closeNow();
client.closeNow();
return;
}
@@ -171,7 +173,7 @@ public class EnterWorld extends GameClientPacket
html.setFile("data/html/clan_notice.htm");
html.replace("%clan_name%", player.getClan().getName());
html.replace("%notice_text%", player.getClan().getNotice().replaceAll("\r\n", "<br>").replaceAll("action", "").replace("bypass", ""));
sendPacket(html);
player.sendPacket(html);
}
}
@@ -185,7 +187,7 @@ public class EnterWorld extends GameClientPacket
// player.sendPacket(new StopRotation(player, player.getHeading(), 10000000));
if (SevenSigns.getInstance().isSealValidationPeriod())
{
sendPacket(new SignsSky());
player.sendPacket(new SignsSky());
}
// Buff and Status icons
@@ -258,7 +260,7 @@ public class EnterWorld extends GameClientPacket
player.sendMessage("[Server]: You have over enchanted items you will be kicked from server!");
player.sendMessage("[Server]: Respect our server rules.");
// Message with screen
sendPacket(new ExShowScreenMessage(" You have an over enchanted item, you will be kicked from server! ", 6000));
player.sendPacket(new ExShowScreenMessage(" You have an over enchanted item, you will be kicked from server! ", 6000));
// Punishment e LOGGER in audit
Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " has Overenchanted item! Kicked! ", Config.DEFAULT_PUNISH);
// Logger in console
@@ -277,12 +279,12 @@ public class EnterWorld extends GameClientPacket
player.getMacroses().sendUpdate();
// Send packets info
sendPacket(new ClientSetTime()); // SetClientTime
sendPacket(new UserInfo(player));
sendPacket(new HennaInfo(player));
sendPacket(new FriendList(player));
sendPacket(new ItemList(player, false));
sendPacket(new ShortCutInit(player));
player.sendPacket(new ClientSetTime()); // SetClientTime
player.sendPacket(new UserInfo(player));
player.sendPacket(new HennaInfo(player));
player.sendPacket(new FriendList(player));
player.sendPacket(new ItemList(player, false));
player.sendPacket(new ShortCutInit(player));
// Reload inventory to give SA skill
player.getInventory().reloadEquippedItems();
@@ -315,13 +317,13 @@ public class EnterWorld extends GameClientPacket
// sendPacket(ui);
if ((player.getClanId() != 0) && (player.getClan() != null))
{
sendPacket(new PledgeShowMemberListAll(player.getClan(), player));
sendPacket(new PledgeStatusChanged(player.getClan()));
player.sendPacket(new PledgeShowMemberListAll(player.getClan(), player));
player.sendPacket(new PledgeStatusChanged(player.getClan()));
}
if (player.isAlikeDead())
{
sendPacket(new Die(player)); // No broadcast needed since the player will already spawn dead to others
player.sendPacket(new Die(player)); // No broadcast needed since the player will already spawn dead to others
}
if (Config.ALLOW_WATER)
@@ -491,13 +493,13 @@ public class EnterWorld extends GameClientPacket
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.IT_IS_NOW_MIDNIGHT_AND_THE_EFFECT_OF_S1_CAN_BE_FELT);
sm.addSkillName(294);
sendPacket(sm);
player.sendPacket(sm);
}
else
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.IT_IS_DAWN_AND_THE_EFFECT_OF_S1_WILL_NOW_DISAPPEAR);
sm.addSkillName(294);
sendPacket(sm);
player.sendPacket(sm);
}
}
}
@@ -536,7 +538,7 @@ public class EnterWorld extends GameClientPacket
}
catch (PatternSyntaxException e) // case of illegal pattern
{
LOGGER.warning("ERROR " + getType() + ": Character name pattern of config is wrong!");
LOGGER.warning("Character name pattern of config is wrong!");
pattern = Pattern.compile(".*");
}
@@ -641,7 +643,7 @@ public class EnterWorld extends GameClientPacket
final NpcHtmlMessage html = new NpcHtmlMessage(1);
html.setFile(Welcome_Path);
html.replace("%name%", player.getName());
sendPacket(html);
player.sendPacket(html);
}
}
@@ -743,11 +745,11 @@ public class EnterWorld extends GameClientPacket
player.updateNameTitleColor();
sendPacket(new UserInfo(player));
sendPacket(new HennaInfo(player));
sendPacket(new FriendList(player));
sendPacket(new ItemList(player, false));
sendPacket(new ShortCutInit(player));
player.sendPacket(new UserInfo(player));
player.sendPacket(new HennaInfo(player));
player.sendPacket(new FriendList(player));
player.sendPacket(new ItemList(player, false));
player.sendPacket(new ShortCutInit(player));
player.broadcastUserInfo();
player.sendPacket(new EtcStatusUpdate(player));
}

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 org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.IIncomingPacket;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.ExIncomingPackets;
import org.l2jmobius.gameserver.network.GameClient;
/**
* @author Nos
*/
public class ExPacket implements IClientIncomingPacket
{
// private static final Logger LOGGER = Logger.getLogger(ExPacket.class.getName());
private ExIncomingPackets _exIncomingPacket;
private IIncomingPacket<GameClient> _exPacket;
@Override
public boolean read(GameClient client, PacketReader packet)
{
final int exPacketId = packet.readH() & 0xFFFF;
if ((exPacketId < 0) || (exPacketId >= ExIncomingPackets.PACKET_ARRAY.length))
{
return false;
}
_exIncomingPacket = ExIncomingPackets.PACKET_ARRAY[exPacketId];
if (_exIncomingPacket == null)
{
// LOGGER.finer(getClass().getSimpleName() + ": Unknown packet: " + Integer.toHexString(exPacketId));
return false;
}
_exPacket = _exIncomingPacket.newIncomingPacket();
return (_exPacket != null) && _exPacket.read(client, packet);
}
@Override
public void run(GameClient client) throws Exception
{
if (!_exIncomingPacket.getConnectionStates().contains(client.getConnectionState()))
{
// LOGGER.finer(_exIncomingPacket + ": Connection at invalid state: " + client.getConnectionState() + " Required State: " + _exIncomingPacket.getConnectionStates());
return;
}
_exPacket.run(client);
}
}

View File

@@ -17,31 +17,32 @@
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.StopRotation;
@SuppressWarnings("unused")
public class FinishRotating extends GameClientPacket
public class FinishRotating implements IClientIncomingPacket
{
private int _degree;
private int _unknown;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_degree = readD();
_unknown = readD();
_degree = packet.readD();
packet.readD(); // Unknown.
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
if (!Config.ENABLE_KEYBOARD_MOVEMENT)
{
return;
}
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -1,92 +0,0 @@
/*
* 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 org.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Logger;
import org.l2jmobius.commons.mmocore.ReceivablePacket;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
/**
* Packets received by the game server from clients
* @author KenM
*/
public abstract class GameClientPacket extends ReceivablePacket<GameClient>
{
protected static final Logger LOGGER = Logger.getLogger(GameClientPacket.class.getName());
@Override
protected boolean read()
{
try
{
readImpl();
return true;
}
catch (Exception e)
{
LOGGER.severe("Client: " + getClient() + " - Failed reading: " + getType() + " ; " + e.getMessage() + " " + e);
}
return false;
}
protected abstract void readImpl();
@Override
public void run()
{
try
{
runImpl();
if ((this instanceof MoveBackwardToLocation) || (this instanceof AttackRequest) || (this instanceof RequestMagicSkillUse))
{
if (getClient().getPlayer() != null)
{
getClient().getPlayer().onActionRequest(); // Removes onSpawn Protection
}
}
}
catch (Throwable t)
{
LOGGER.severe("Client: " + getClient() + " - Failed reading: " + getType() + " ; " + t.getMessage() + " " + t);
if (this instanceof EnterWorld)
{
getClient().closeNow();
}
}
}
protected abstract void runImpl();
/**
* Sends a game server packet to the client.
* @param gsp the game server packet
*/
protected final void sendPacket(GameServerPacket gsp)
{
getClient().sendPacket(gsp);
}
/**
* @return A String with this packet name for debuging purposes
*/
public String getType()
{
return "[C] " + getClass().getSimpleName();
}
}

View File

@@ -16,25 +16,29 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.GameClient;
/**
* @author zabbix Lets drink to code! Unknown Packet: ca 0000: 45 00 01 00 1e 37 a2 f5 00 00 00 00 00 00 00 00 E....7..........
*/
public class GameGuardReply extends GameClientPacket
public class GameGuardReply implements IClientIncomingPacket
{
private final int[] _reply = new int[4];
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_reply[0] = readD();
_reply[1] = readD();
_reply[2] = readD();
_reply[3] = readD();
_reply[0] = packet.readD();
_reply[1] = packet.readD();
_reply[2] = packet.readD();
_reply[3] = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
getClient().setGameGuardOk(true);
client.setGameGuardOk(true);
}
}

View File

@@ -16,18 +16,16 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.IIncomingPacket;
import org.l2jmobius.gameserver.network.GameClient;
/**
* @author zabbix Lets drink to code!
* Packets received by the game serv@Override er from clients
* @author KenM
*/
public class DummyPacket extends GameClientPacket
public interface IClientIncomingPacket extends IIncomingPacket<GameClient>
{
@Override
protected void readImpl()
{
}
@Override
public void runImpl()
{
}
}
Logger LOGGER = Logger.getLogger(IClientIncomingPacket.class.getName());
}

View File

@@ -17,6 +17,7 @@
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.SkillTable;
import org.l2jmobius.gameserver.model.Party;
@@ -25,23 +26,25 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
import org.l2jmobius.gameserver.model.sevensigns.SevenSignsFestival;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
public class Logout extends GameClientPacket
public class Logout implements IClientIncomingPacket
{
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
// Do not allow leaving if player is fighting
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -19,10 +19,12 @@ package org.l2jmobius.gameserver.network.clientpackets;
import java.nio.BufferUnderflowException;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.xml.DoorData;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.EnchantResult;
@@ -30,7 +32,7 @@ import org.l2jmobius.gameserver.network.serverpackets.StopMove;
import org.l2jmobius.gameserver.util.IllegalPlayerAction;
import org.l2jmobius.gameserver.util.Util;
public class MoveBackwardToLocation extends GameClientPacket
public class MoveBackwardToLocation implements IClientIncomingPacket
{
private int _targetX;
private int _targetY;
@@ -41,42 +43,44 @@ public class MoveBackwardToLocation extends GameClientPacket
private int _movementMode;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_targetX = readD();
_targetY = readD();
_targetZ = readD();
_originX = readD();
_originY = readD();
_originZ = readD();
_targetX = packet.readD();
_targetY = packet.readD();
_targetZ = packet.readD();
_originX = packet.readD();
_originY = packet.readD();
_originZ = packet.readD();
try
{
_movementMode = readD(); // is 0 if cursor keys are used 1 if mouse is used
_movementMode = packet.readD(); // is 0 if cursor keys are used 1 if mouse is used
}
catch (BufferUnderflowException e)
{
// Ignore for now
if (Config.L2WALKER_PROTECTION)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
player.sendPacket(SystemMessageId.A_HACKING_TOOL_HAS_BEEN_DISCOVERED_PLEASE_TRY_PLAYING_AGAIN_AFTER_CLOSING_UNNECESSARY_PROGRAMS);
Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " trying to use L2Walker!", IllegalPlayerAction.PUNISH_KICK);
}
}
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
}
// Move flood protection
if (!getClient().getFloodProtectors().getMoveAction().tryPerformAction("MoveBackwardToLocation"))
if (!client.getFloodProtectors().getMoveAction().tryPerformAction("MoveBackwardToLocation"))
{
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
@@ -85,7 +89,7 @@ public class MoveBackwardToLocation extends GameClientPacket
// Like L2OFF movements prohibited when char is sitting
if (player.isSitting())
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}

View File

@@ -16,27 +16,26 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.GameClient;
/**
* Format: (c) ddd d: dx d: dy d: dz
* @author -Wooden-
*/
@SuppressWarnings("unused")
public class MoveWithDelta extends GameClientPacket
public class MoveWithDelta implements IClientIncomingPacket
{
private int _dx;
private int _dy;
private int _dz;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_dx = readD();
_dy = readD();
_dz = readD();
packet.readD(); // dx
packet.readD(); // dy
packet.readD(); // dz
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
}
}

View File

@@ -21,6 +21,7 @@ import java.util.List;
import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.data.ItemTable;
import org.l2jmobius.gameserver.data.xml.MultisellData;
import org.l2jmobius.gameserver.model.Augmentation;
@@ -34,6 +35,7 @@ import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.multisell.MultiSellEntry;
import org.l2jmobius.gameserver.model.multisell.MultiSellIngredient;
import org.l2jmobius.gameserver.model.multisell.MultiSellListContainer;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.ItemList;
@@ -44,7 +46,7 @@ import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* The Class MultiSellChoose.
*/
public class MultiSellChoose extends GameClientPacket
public class MultiSellChoose implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(MultiSellChoose.class.getName());
private int _listId;
@@ -54,27 +56,28 @@ public class MultiSellChoose extends GameClientPacket
private int _transactionTax; // local handling of taxation
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_listId = readD();
_entryId = readD();
_amount = readD();
// _enchantment = readH(); // Commented this line because it did NOT work!
_listId = packet.readD();
_entryId = packet.readD();
_amount = packet.readD();
// _enchantment = packet.readH(); // Commented this line because it did NOT work!
_enchantment = _entryId % 100000;
_entryId = _entryId / 100000;
_transactionTax = 0; // Initialize tax amount to 0...
return true;
}
@Override
public void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
}
if (!getClient().getFloodProtectors().getMultiSell().tryPerformAction("multisell choose"))
if (!client.getFloodProtectors().getMultiSell().tryPerformAction("multisell choose"))
{
player.setMultiSellId(-1);
return;

View File

@@ -16,20 +16,23 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.data.xml.PlayerTemplateData;
import org.l2jmobius.gameserver.enums.ClassId;
import org.l2jmobius.gameserver.model.actor.templates.PlayerTemplate;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.CharTemplates;
public class NewCharacter extends GameClientPacket
public class NewCharacter implements IClientIncomingPacket
{
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final CharTemplates ct = new CharTemplates();
PlayerTemplate template = PlayerTemplateData.getInstance().getTemplate(0);
@@ -63,6 +66,6 @@ public class NewCharacter extends GameClientPacket
ct.addChar(template);
// Finally
sendPacket(ct);
client.sendPacket(ct);
}
}

View File

@@ -16,19 +16,22 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
public class ObserverReturn extends GameClientPacket
public class ObserverReturn implements IClientIncomingPacket
{
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;

View File

@@ -19,37 +19,40 @@ package org.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Logger;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.KeyPacket;
public class ProtocolVersion extends GameClientPacket
public class ProtocolVersion implements IClientIncomingPacket
{
static Logger LOGGER = Logger.getLogger(ProtocolVersion.class.getName());
private int _version;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_version = readD();
_version = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
if ((_version == 65534) || (_version == -2)) // Ping
{
getClient().close((GameServerPacket) null);
// this is just a ping attempt from the new C2 client
client.closeNow();
}
else if ((_version < Config.MIN_PROTOCOL_REVISION) || (_version > Config.MAX_PROTOCOL_REVISION))
{
LOGGER.info("Client: " + getClient() + " -> Protocol Revision: " + _version + " is invalid. Minimum is " + Config.MIN_PROTOCOL_REVISION + " and Maximum is " + Config.MAX_PROTOCOL_REVISION + " are supported. Closing connection.");
LOGGER.info("Client: " + client + " -> Protocol Revision: " + _version + " is invalid. Minimum is " + Config.MIN_PROTOCOL_REVISION + " and Maximum is " + Config.MAX_PROTOCOL_REVISION + " are supported. Closing connection.");
LOGGER.warning("Wrong Protocol Version " + _version);
getClient().close((GameServerPacket) null);
client.close(new KeyPacket(client.enableCrypt(), 0));
}
else
{
getClient().setProtocolVersion(_version);
getClient().sendPacket(new KeyPacket(getClient().enableCrypt()));
client.sendPacket(new KeyPacket(client.enableCrypt(), 1));
client.setProtocolVersion(_version);
}
}
}

View File

@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.GameTimeController;
import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.data.SkillTable;
@@ -39,6 +40,7 @@ import org.l2jmobius.gameserver.model.actor.instance.StaticObjectInstance;
import org.l2jmobius.gameserver.model.actor.instance.SummonInstance;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import org.l2jmobius.gameserver.network.serverpackets.ChairSit;
@@ -46,7 +48,7 @@ import org.l2jmobius.gameserver.network.serverpackets.RecipeShopManageList;
import org.l2jmobius.gameserver.network.serverpackets.Ride;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public class RequestActionUse extends GameClientPacket
public class RequestActionUse implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(RequestActionUse.class.getName());
@@ -70,17 +72,18 @@ public class RequestActionUse extends GameClientPacket
}
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_actionId = readD();
_ctrlPressed = readD() == 1;
_shiftPressed = readC() == 1;
_actionId = packet.readD();
_ctrlPressed = packet.readD() == 1;
_shiftPressed = packet.readC() == 1;
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
@@ -89,14 +92,14 @@ public class RequestActionUse extends GameClientPacket
// dont do anything if player is dead
if ((_actionId != 0) && player.isAlikeDead())
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// don't do anything if player is confused
if (player.isOutOfControl())
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
@@ -107,7 +110,7 @@ public class RequestActionUse extends GameClientPacket
}
else if (player.isCastingNow())
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
@@ -337,31 +340,31 @@ public class RequestActionUse extends GameClientPacket
}
case 32: // Wild Hog Cannon - Mode Change
{
useSkill(4230);
useSkill(client, 4230);
break;
}
case 36: // Soulless - Toxic Smoke
{
useSkill(4259);
useSkill(client, 4259);
break;
}
case 37:
{
if (player.isAlikeDead())
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Like L2OFF - You can't open Manufacture when you are in private store
if ((player.getPrivateStoreType() == PlayerInstance.STORE_PRIVATE_BUY) || (player.getPrivateStoreType() == PlayerInstance.STORE_PRIVATE_SELL))
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Like L2OFF - You can't open Manufacture when you are sitting
if (player.isSitting() && (player.getPrivateStoreType() != PlayerInstance.STORE_PRIVATE_MANUFACTURE))
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (player.getPrivateStoreType() == PlayerInstance.STORE_PRIVATE_MANUFACTURE)
@@ -381,47 +384,47 @@ public class RequestActionUse extends GameClientPacket
}
case 39: // Soulless - Parasite Burst
{
useSkill(4138);
useSkill(client, 4138);
break;
}
case 41: // Wild Hog Cannon - Attack
{
useSkill(4230);
useSkill(client, 4230);
break;
}
case 42: // Kai the Cat - Self Damage Shield
{
useSkill(4378, player);
useSkill(client, 4378, player);
break;
}
case 43: // Unicorn Merrow - Hydro Screw
{
useSkill(4137);
useSkill(client, 4137);
break;
}
case 44: // Big Boom - Boom Attack
{
useSkill(4139);
useSkill(client, 4139);
break;
}
case 45: // Unicorn Boxer - Master Recharge
{
useSkill(4025, player);
useSkill(client, 4025, player);
break;
}
case 46: // Mew the Cat - Mega Storm Strike
{
useSkill(4261);
useSkill(client, 4261);
break;
}
case 47: // Silhouette - Steal Blood
{
useSkill(4260);
useSkill(client, 4260);
break;
}
case 48: // Mechanic Golem - Mech. Cannon
{
useSkill(4068);
useSkill(client, 4068);
break;
}
case 51:
@@ -429,19 +432,19 @@ public class RequestActionUse extends GameClientPacket
// Player shouldn't be able to set stores if he/she is alike dead (dead or fake death)
if (player.isAlikeDead())
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Like L2OFF - You can't open Manufacture when you are in private store
if ((player.getPrivateStoreType() == PlayerInstance.STORE_PRIVATE_BUY) || (player.getPrivateStoreType() == PlayerInstance.STORE_PRIVATE_SELL))
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Like L2OFF - You can't open Manufacture when you are sitting
if (player.isSitting() && (player.getPrivateStoreType() != PlayerInstance.STORE_PRIVATE_MANUFACTURE))
{
getClient().sendPacket(ActionFailed.STATIC_PACKET);
player.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (player.getPrivateStoreType() == PlayerInstance.STORE_PRIVATE_MANUFACTURE)
@@ -511,7 +514,7 @@ public class RequestActionUse extends GameClientPacket
{
if (target instanceof DoorInstance)
{
useSkill(4079);
useSkill(client, 4079);
}
break;
}
@@ -521,124 +524,124 @@ public class RequestActionUse extends GameClientPacket
}
case 1003: // Wind Hatchling/Strider - Wild Stun
{
useSkill(4710); // TODO use correct skill level based on pet level
useSkill(client, 4710); // TODO use correct skill level based on pet level
break;
}
case 1004: // Wind Hatchling/Strider - Wild Defense
{
useSkill(4711, player); // TODO use correct skill level based on pet level
useSkill(client, 4711, player); // TODO use correct skill level based on pet level
break;
}
case 1005: // Star Hatchling/Strider - Bright Burst
{
useSkill(4712); // TODO use correct skill level based on pet level
useSkill(client, 4712); // TODO use correct skill level based on pet level
break;
}
case 1006: // Star Hatchling/Strider - Bright Heal
{
useSkill(4713, player); // TODO use correct skill level based on pet level
useSkill(client, 4713, player); // TODO use correct skill level based on pet level
break;
}
case 1007: // Cat Queen - Blessing of Queen
{
useSkill(4699, player);
useSkill(client, 4699, player);
break;
}
case 1008: // Cat Queen - Gift of Queen
{
useSkill(4700, player);
useSkill(client, 4700, player);
break;
}
case 1009: // Cat Queen - Cure of Queen
{
useSkill(4701);
useSkill(client, 4701);
break;
}
case 1010: // Unicorn Seraphim - Blessing of Seraphim
{
useSkill(4702, player);
useSkill(client, 4702, player);
break;
}
case 1011: // Unicorn Seraphim - Gift of Seraphim
{
useSkill(4703, player);
useSkill(client, 4703, player);
break;
}
case 1012: // Unicorn Seraphim - Cure of Seraphim
{
useSkill(4704);
useSkill(client, 4704);
break;
}
case 1013: // Nightshade - Curse of Shade
{
useSkill(4705);
useSkill(client, 4705);
break;
}
case 1014: // Nightshade - Mass Curse of Shade
{
useSkill(4706, player);
useSkill(client, 4706, player);
break;
}
case 1015: // Nightshade - Shade Sacrifice
{
useSkill(4707);
useSkill(client, 4707);
break;
}
case 1016: // Cursed Man - Cursed Blow
{
useSkill(4709);
useSkill(client, 4709);
break;
}
case 1017: // Cursed Man - Cursed Strike/Stun
{
useSkill(4708);
useSkill(client, 4708);
break;
}
case 1031: // Feline King - Slash
{
useSkill(5135);
useSkill(client, 5135);
break;
}
case 1032: // Feline King - Spinning Slash
{
useSkill(5136);
useSkill(client, 5136);
break;
}
case 1033: // Feline King - Grip of the Cat
{
useSkill(5137);
useSkill(client, 5137);
break;
}
case 1034: // Magnus the Unicorn - Whiplash
{
useSkill(5138);
useSkill(client, 5138);
break;
}
case 1035: // Magnus the Unicorn - Tridal Wave
{
useSkill(5139);
useSkill(client, 5139);
break;
}
case 1036: // Spectral Lord - Corpse Kaboom
{
useSkill(5142);
useSkill(client, 5142);
break;
}
case 1037: // Spectral Lord - Dicing Death
{
useSkill(5141);
useSkill(client, 5141);
break;
}
case 1038: // Spectral Lord - Force Curse
{
useSkill(5140);
useSkill(client, 5140);
break;
}
case 1039: // Swoop Cannon - Cannon Fodder
{
if (!(target instanceof DoorInstance))
{
useSkill(5110);
useSkill(client, 5110);
}
break;
}
@@ -646,7 +649,7 @@ public class RequestActionUse extends GameClientPacket
{
if (!(target instanceof DoorInstance))
{
useSkill(5111);
useSkill(client, 5111);
}
break;
}
@@ -660,9 +663,9 @@ public class RequestActionUse extends GameClientPacket
/*
* Cast a skill for active pet/servitor. Target is specified as a parameter but can be overwrited or ignored depending on skill type.
*/
private void useSkill(int skillId, WorldObject target)
private void useSkill(GameClient client, int skillId, WorldObject target)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
@@ -705,14 +708,14 @@ public class RequestActionUse extends GameClientPacket
/*
* Cast a skill for active pet/servitor. Target is retrieved from owner' target, then validated by overloaded method useSkill(int, Creature).
*/
private void useSkill(int skillId)
private void useSkill(GameClient client, int skillId)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
}
useSkill(skillId, player.getTarget());
useSkill(client, skillId, player.getTarget());
}
}

View File

@@ -16,9 +16,11 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.AllyCrest;
public class RequestAllyCrest extends GameClientPacket
public class RequestAllyCrest implements IClientIncomingPacket
{
private int _crestId;
@@ -26,14 +28,15 @@ public class RequestAllyCrest extends GameClientPacket
* packet type id 0x88 format: cd
*/
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_crestId = readD();
_crestId = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
sendPacket(new AllyCrest(_crestId));
client.sendPacket(new AllyCrest(_crestId));
}
}

View File

@@ -16,18 +16,21 @@
*/
package org.l2jmobius.gameserver.network.clientpackets;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.serverpackets.AllyInfo;
public class RequestAllyInfo extends GameClientPacket
public class RequestAllyInfo implements IClientIncomingPacket
{
@Override
public void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
sendPacket(new AllyInfo(getClient().getPlayer()));
client.sendPacket(new AllyInfo(client.getPlayer()));
}
}

View File

@@ -21,7 +21,9 @@ import java.sql.PreparedStatement;
import java.util.logging.Logger;
import org.l2jmobius.commons.database.DatabaseFactory;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.FriendList;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
@@ -29,22 +31,23 @@ import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* sample 5F 01 00 00 00 format cdd
*/
public class RequestAnswerFriendInvite extends GameClientPacket
public class RequestAnswerFriendInvite implements IClientIncomingPacket
{
private static final Logger LOGGER = Logger.getLogger(RequestAnswerFriendInvite.class.getName());
private int _response;
@Override
protected void readImpl()
public boolean read(GameClient client, PacketReader packet)
{
_response = readD();
_response = packet.readD();
return true;
}
@Override
protected void runImpl()
public void run(GameClient client)
{
final PlayerInstance player = getClient().getPlayer();
final PlayerInstance player = client.getPlayer();
if (player != null)
{
final PlayerInstance requestor = player.getActiveRequester();

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