Move some remaining bits and pieces to netty implementation, start cleaning up
This commit is contained in:
@@ -91,6 +91,8 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
|
||||
public static final String CLIENT_NIBBLEHWID = "HWID2";
|
||||
public static final String CLIENT_REMOTE_ADDRESS = "REMOTE_IP";
|
||||
|
||||
private final Type type;
|
||||
|
||||
private Hwid hwid;
|
||||
private String remoteHwid; // Mac address + hwid in one. Retrieved from client when attempting to enter game.
|
||||
private String remoteAddress;
|
||||
@@ -136,6 +138,11 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
|
||||
private long lastPacket = System.currentTimeMillis();
|
||||
private int lang = 0;
|
||||
|
||||
public enum Type {
|
||||
LOGIN,
|
||||
CHANNEL
|
||||
}
|
||||
|
||||
public void updateLastPacket() {
|
||||
lastPacket = System.currentTimeMillis();
|
||||
}
|
||||
@@ -144,17 +151,23 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
|
||||
return lastPacket;
|
||||
}
|
||||
|
||||
public MapleClient(PacketProcessor packetProcessor, int world, int channel) {
|
||||
public MapleClient(Type type, PacketProcessor packetProcessor, int world, int channel) {
|
||||
this.type = type;
|
||||
this.packetProcessor = packetProcessor;
|
||||
this.world = world;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public MapleClient(MapleAESOFB send, MapleAESOFB receive, IoSession session) {
|
||||
this.type = null;
|
||||
this.send = send;
|
||||
this.receive = receive;
|
||||
}
|
||||
|
||||
public static MapleClient createMock() {
|
||||
return new MapleClient(null, null, -123, -123);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
final io.netty.channel.Channel channel = ctx.channel();
|
||||
@@ -209,7 +222,6 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
updateLastPacket();
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,18 +238,23 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
if (cause instanceof InvalidPacketHeaderException) {
|
||||
// TODO close session through MapleSessionCoordinator
|
||||
MapleSessionCoordinator.getInstance().closeSession(this, true);
|
||||
} else if (cause instanceof IOException) {
|
||||
closeSession();
|
||||
} else {
|
||||
|
||||
closeMapleSession();
|
||||
}
|
||||
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) {
|
||||
closeMapleSession();
|
||||
}
|
||||
|
||||
private void closeMapleSession() {
|
||||
switch (type) {
|
||||
case LOGIN -> MapleSessionCoordinator.getInstance().closeLoginSession(this);
|
||||
case CHANNEL -> MapleSessionCoordinator.getInstance().closeSession(this, null);
|
||||
}
|
||||
|
||||
try {
|
||||
// client freeze issues on session transition states found thanks to yolinlin, Omo Oppa, Nozphex
|
||||
if (!inTransition) {
|
||||
@@ -245,6 +262,8 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.warn("Account stuck", t);
|
||||
} finally {
|
||||
closeSession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,306 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net;
|
||||
|
||||
import client.MapleClient;
|
||||
import config.YamlConfig;
|
||||
import constants.net.ServerConstants;
|
||||
import net.netty.InitializationVector;
|
||||
import net.server.Server;
|
||||
import net.server.audit.LockCollector;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import net.server.coordinator.session.IpAddresses;
|
||||
import net.server.coordinator.session.MapleSessionCoordinator;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IdleStatus;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import server.TimerManager;
|
||||
import tools.FilePrinter;
|
||||
import tools.MapleAESOFB;
|
||||
import tools.MapleLogger;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.ByteArrayByteStream;
|
||||
import tools.data.input.GenericSeekableLittleEndianAccessor;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class MapleServerHandler extends IoHandlerAdapter {
|
||||
private final static Set<Short> ignoredDebugRecvPackets = new HashSet<>(Arrays.asList((short) 167, (short) 197, (short) 89, (short) 91, (short) 41, (short) 188, (short) 107));
|
||||
|
||||
private PacketProcessor processor;
|
||||
private int world = -1, channel = -1;
|
||||
private static final SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm");
|
||||
private static AtomicLong sessionId = new AtomicLong(7777);
|
||||
|
||||
private MonitoredReentrantLock idleLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SRVHANDLER_IDLE, true);
|
||||
private MonitoredReentrantLock tempLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SRVHANDLER_TEMP, true);
|
||||
private Map<MapleClient, Long> idleSessions = new HashMap<>(100);
|
||||
private Map<MapleClient, Long> tempIdleSessions = new HashMap<>();
|
||||
private ScheduledFuture<?> idleManager = null;
|
||||
|
||||
public MapleServerHandler() {
|
||||
this.processor = PacketProcessor.getProcessor(-1, -1);
|
||||
|
||||
idleManagerTask();
|
||||
}
|
||||
|
||||
public MapleServerHandler(int world, int channel) {
|
||||
this.processor = PacketProcessor.getProcessor(world, channel);
|
||||
this.world = world;
|
||||
this.channel = channel;
|
||||
|
||||
idleManagerTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause) {
|
||||
if (cause instanceof IOException) {
|
||||
closeMapleSession(session);
|
||||
} else {
|
||||
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
|
||||
|
||||
if (client != null && client.getPlayer() != null) {
|
||||
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, cause, "Exception caught by: " + client.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLoginServerHandler() {
|
||||
return channel == -1 && world == -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionOpened(IoSession session) {
|
||||
String remoteHost;
|
||||
try {
|
||||
remoteHost = ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
|
||||
|
||||
if (remoteHost == null) {
|
||||
remoteHost = "null";
|
||||
} else {
|
||||
remoteHost = IpAddresses.evaluateRemoteAddress(remoteHost); // thanks dyz for noticing Local/LAN/WAN connections not interacting properly
|
||||
}
|
||||
} catch (NullPointerException npe) { // thanks Agassy, Alchemist for pointing out possibility of remoteHost = null.
|
||||
remoteHost = "null";
|
||||
}
|
||||
|
||||
session.setAttribute(MapleClient.CLIENT_REMOTE_ADDRESS, remoteHost);
|
||||
|
||||
if (!Server.getInstance().isOnline()) {
|
||||
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
final InitializationVector ivSend = InitializationVector.generateSend();
|
||||
final InitializationVector ivRecv = InitializationVector.generateReceive();
|
||||
MapleAESOFB sendCypher = new MapleAESOFB(ivSend, (short) (0xFFFF - ServerConstants.VERSION));
|
||||
MapleAESOFB recvCypher = new MapleAESOFB(ivRecv, ServerConstants.VERSION);
|
||||
MapleClient client = new MapleClient(sendCypher, recvCypher, session);
|
||||
|
||||
if (!isLoginServerHandler()) {
|
||||
if (Server.getInstance().getChannel(world, channel) == null) {
|
||||
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), true);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!MapleSessionCoordinator.getInstance().canStartLoginSession(client)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FilePrinter.print(FilePrinter.SESSION, "IoSession with " + session.getRemoteAddress() + " opened on " + sdf.format(Calendar.getInstance().getTime()), false);
|
||||
}
|
||||
|
||||
client.setWorld(world);
|
||||
client.setChannel(channel);
|
||||
client.setSessionId(sessionId.getAndIncrement()); // Generates a reasonable session id.
|
||||
session.write(MaplePacketCreator.getHello(ServerConstants.VERSION, ivSend, ivRecv));
|
||||
session.setAttribute(MapleClient.CLIENT_KEY, client);
|
||||
}
|
||||
|
||||
private void closeMapleSession(IoSession session) {
|
||||
if (isLoginServerHandler()) {
|
||||
MapleSessionCoordinator.getInstance().closeLoginSession(MapleClient.getPlaceholder());
|
||||
} else {
|
||||
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), null);
|
||||
}
|
||||
|
||||
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
|
||||
if (client != null) {
|
||||
try {
|
||||
// client freeze issues on session transition states found thanks to yolinlin, Omo Oppa, Nozphex
|
||||
if (!client.isInTransition()) {
|
||||
client.disconnect(false, false);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
FilePrinter.printError(FilePrinter.ACCOUNT_STUCK, t);
|
||||
} finally {
|
||||
session.close();
|
||||
session.removeAttribute(MapleClient.CLIENT_KEY);
|
||||
//client.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionClosed(IoSession session) throws Exception {
|
||||
closeMapleSession(session);
|
||||
super.sessionClosed(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(IoSession session, Object message) {
|
||||
byte[] content = (byte[]) message;
|
||||
SeekableLittleEndianAccessor slea = new GenericSeekableLittleEndianAccessor(new ByteArrayByteStream(content));
|
||||
short packetId = slea.readShort();
|
||||
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
|
||||
|
||||
if(YamlConfig.config.server.USE_DEBUG_SHOW_RCVD_PACKET && !ignoredDebugRecvPackets.contains(packetId)) System.out.println("Received packet id " + packetId);
|
||||
final MaplePacketHandler packetHandler = processor.getHandler(packetId);
|
||||
if (packetHandler != null && packetHandler.validateState(client)) {
|
||||
try {
|
||||
MapleLogger.logRecv(client, packetId, message);
|
||||
packetHandler.handlePacket(slea, client);
|
||||
} catch (final Throwable t) {
|
||||
FilePrinter.printError(FilePrinter.PACKET_HANDLER + packetHandler.getClass().getName() + ".txt", t, "Error for " + (client.getPlayer() == null ? "" : "player ; " + client.getPlayer() + " on map ; " + client.getPlayer().getMapId() + " - ") + "account ; " + client.getAccountName() + "\r\n" + slea.toString());
|
||||
//client.announce(MaplePacketCreator.enableActions());//bugs sometimes
|
||||
}
|
||||
client.updateLastPacket();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageSent(IoSession session, Object message) {
|
||||
byte[] content = (byte[]) message;
|
||||
SeekableLittleEndianAccessor slea = new GenericSeekableLittleEndianAccessor(new ByteArrayByteStream(content));
|
||||
slea.readShort(); //packetId
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionIdle(final IoSession session, final IdleStatus status) throws Exception {
|
||||
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
|
||||
if (client != null) {
|
||||
registerIdleSession(client);
|
||||
}
|
||||
super.sessionIdle(session, status);
|
||||
}
|
||||
|
||||
private void registerIdleSession(MapleClient c) {
|
||||
if(idleLock.tryLock()) {
|
||||
try {
|
||||
idleSessions.put(c, Server.getInstance().getCurrentTime());
|
||||
c.announce(MaplePacketCreator.getPing());
|
||||
} finally {
|
||||
idleLock.unlock();
|
||||
}
|
||||
} else {
|
||||
tempLock.lock();
|
||||
try {
|
||||
tempIdleSessions.put(c, Server.getInstance().getCurrentTime());
|
||||
c.announce(MaplePacketCreator.getPing());
|
||||
} finally {
|
||||
tempLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void manageIdleSessions() {
|
||||
long timeNow = Server.getInstance().getCurrentTime();
|
||||
long timeThen = timeNow - 15000;
|
||||
|
||||
Set<MapleClient> pingClients = new HashSet<>();
|
||||
idleLock.lock();
|
||||
try {
|
||||
for(Entry<MapleClient, Long> mc : idleSessions.entrySet()) {
|
||||
if(timeNow - mc.getValue() >= 15000) {
|
||||
pingClients.add(mc.getKey());
|
||||
}
|
||||
}
|
||||
idleSessions.clear();
|
||||
|
||||
if(!tempIdleSessions.isEmpty()) {
|
||||
tempLock.lock();
|
||||
try {
|
||||
for(Entry<MapleClient, Long> mc : tempIdleSessions.entrySet()) {
|
||||
idleSessions.put(mc.getKey(), mc.getValue());
|
||||
}
|
||||
|
||||
tempIdleSessions.clear();
|
||||
} finally {
|
||||
tempLock.unlock();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
idleLock.unlock();
|
||||
}
|
||||
|
||||
for(MapleClient c : pingClients) {
|
||||
c.testPing(timeThen);
|
||||
}
|
||||
}
|
||||
|
||||
private void idleManagerTask() {
|
||||
this.idleManager = TimerManager.getInstance().register(() -> manageIdleSessions(), 10000);
|
||||
}
|
||||
|
||||
private void cancelIdleManagerTask() {
|
||||
this.idleManager.cancel(false);
|
||||
this.idleManager = null;
|
||||
}
|
||||
|
||||
private void disposeLocks() {
|
||||
LockCollector.getInstance().registerDisposeAction(() -> emptyLocks());
|
||||
}
|
||||
|
||||
private void emptyLocks() {
|
||||
idleLock.dispose();
|
||||
tempLock.dispose();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
cancelIdleManagerTask();
|
||||
|
||||
idleLock.lock();
|
||||
try {
|
||||
idleSessions.clear();
|
||||
} finally {
|
||||
idleLock.unlock();
|
||||
}
|
||||
|
||||
tempLock.lock();
|
||||
try {
|
||||
tempIdleSessions.clear();
|
||||
} finally {
|
||||
tempLock.unlock();
|
||||
}
|
||||
|
||||
disposeLocks();
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package net.netty;
|
||||
import client.MapleClient;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import net.PacketProcessor;
|
||||
import net.server.Server;
|
||||
import net.server.coordinator.session.MapleSessionCoordinator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -20,12 +22,18 @@ public class ChannelServerInitializer extends ServerChannelInitializer {
|
||||
@Override
|
||||
public void initChannel(SocketChannel socketChannel) {
|
||||
final String clientIp = socketChannel.remoteAddress().getHostName();
|
||||
log.debug("Client connected to world {}, channel {} from {}", world, channel, clientIp);
|
||||
log.debug("Client connecting to world {}, channel {} from {}", world, channel, clientIp);
|
||||
|
||||
PacketProcessor packetProcessor = PacketProcessor.getChannelServerProcessor(world, channel);
|
||||
final MapleClient client = new MapleClient(packetProcessor, world, channel);
|
||||
final MapleClient client = new MapleClient(MapleClient.Type.CHANNEL, packetProcessor, world, channel);
|
||||
client.setSessionId(sessionId.getAndIncrement());
|
||||
|
||||
if (Server.getInstance().getChannel(world, channel) == null) {
|
||||
MapleSessionCoordinator.getInstance().closeSession(client, true);
|
||||
socketChannel.close();
|
||||
return;
|
||||
}
|
||||
|
||||
initPipeline(socketChannel, client);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.netty;
|
||||
import client.MapleClient;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import net.PacketProcessor;
|
||||
import net.server.coordinator.session.MapleSessionCoordinator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -15,9 +16,14 @@ public class LoginServerInitializer extends ServerChannelInitializer {
|
||||
log.debug("Client connected to login server from {} ", clientIp);
|
||||
|
||||
PacketProcessor packetProcessor = PacketProcessor.getLoginServerProcessor();
|
||||
final MapleClient client = new MapleClient(packetProcessor, LoginServer.WORLD_ID, LoginServer.CHANNEL_ID);
|
||||
final MapleClient client = new MapleClient(MapleClient.Type.LOGIN, packetProcessor, LoginServer.WORLD_ID, LoginServer.CHANNEL_ID);
|
||||
client.setSessionId(sessionId.getAndIncrement());
|
||||
|
||||
if (!MapleSessionCoordinator.getInstance().canStartLoginSession(client)) {
|
||||
socketChannel.close();
|
||||
return;
|
||||
}
|
||||
|
||||
initPipeline(socketChannel, client);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,6 @@ import constants.game.GameConstants;
|
||||
import constants.inventory.ItemConstants;
|
||||
import constants.net.OpcodeConstants;
|
||||
import constants.net.ServerConstants;
|
||||
import net.MapleServerHandler;
|
||||
import net.mina.MapleCodecFactory;
|
||||
import net.netty.LoginServer;
|
||||
import net.server.audit.ThreadTracker;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
@@ -54,12 +52,6 @@ import net.server.guild.MapleGuild;
|
||||
import net.server.guild.MapleGuildCharacter;
|
||||
import net.server.task.*;
|
||||
import net.server.world.World;
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.apache.mina.core.buffer.SimpleBufferAllocator;
|
||||
import org.apache.mina.core.service.IoAcceptor;
|
||||
import org.apache.mina.core.session.IdleStatus;
|
||||
import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.CashShop.CashItemFactory;
|
||||
@@ -74,8 +66,6 @@ import tools.DatabaseConnection;
|
||||
import tools.FilePrinter;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.Security;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
@@ -106,7 +96,6 @@ public class Server {
|
||||
private static final Map<Integer, Integer> couponRates = new HashMap<>(30);
|
||||
private static final List<Integer> activeCoupons = new LinkedList<>();
|
||||
|
||||
private IoAcceptor acceptor;
|
||||
private LoginServer loginServer;
|
||||
private List<Map<Integer, String>> channels = new LinkedList<>();
|
||||
private List<World> worlds = new ArrayList<>();
|
||||
@@ -931,22 +920,6 @@ public class Server {
|
||||
return loginServer;
|
||||
}
|
||||
|
||||
private IoAcceptor initAcceptor(int port) {
|
||||
IoBuffer.setUseDirectBuffer(false); // join IO operations performed by lxconan
|
||||
IoBuffer.setAllocator(new SimpleBufferAllocator());
|
||||
acceptor = new NioSocketAcceptor();
|
||||
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MapleCodecFactory()));
|
||||
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);
|
||||
acceptor.setHandler(new MapleServerHandler());
|
||||
try {
|
||||
acceptor.bind(new InetSocketAddress(port));
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return acceptor;
|
||||
}
|
||||
|
||||
private static void setAllLoggedOut(Connection con) throws SQLException {
|
||||
try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = 0")) {
|
||||
ps.executeUpdate();
|
||||
@@ -1958,8 +1931,7 @@ public class Server {
|
||||
TimerManager.getInstance().stop();
|
||||
|
||||
System.out.println("Worlds + Channels are offline.");
|
||||
acceptor.unbind();
|
||||
acceptor = null;
|
||||
loginServer.stop();
|
||||
if (!restart) { // shutdown hook deadlocks if System.exit() method is used within its body chores, thanks MIKE for pointing that out
|
||||
new Thread(() -> System.exit(0)).start();
|
||||
} else {
|
||||
|
||||
@@ -24,8 +24,6 @@ package net.server.channel;
|
||||
import client.MapleCharacter;
|
||||
import config.YamlConfig;
|
||||
import constants.game.GameConstants;
|
||||
import net.MapleServerHandler;
|
||||
import net.mina.MapleCodecFactory;
|
||||
import net.netty.ChannelServer;
|
||||
import net.server.PlayerStorage;
|
||||
import net.server.Server;
|
||||
@@ -40,13 +38,6 @@ import net.server.services.type.ChannelServices;
|
||||
import net.server.world.MapleParty;
|
||||
import net.server.world.MaplePartyCharacter;
|
||||
import net.server.world.World;
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.apache.mina.core.buffer.SimpleBufferAllocator;
|
||||
import org.apache.mina.core.service.IoAcceptor;
|
||||
import org.apache.mina.core.session.IdleStatus;
|
||||
import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
||||
import org.apache.mina.transport.socket.SocketSessionConfig;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import scripting.event.EventScriptManager;
|
||||
@@ -59,21 +50,22 @@ import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
public final class Channel {
|
||||
private static final Logger log = LoggerFactory.getLogger(Channel.class);
|
||||
private static final int BASE_PORT = 7575;
|
||||
|
||||
private final int port;
|
||||
private final String ip;
|
||||
private final int world;
|
||||
private final int channel;
|
||||
|
||||
private int port = 7575;
|
||||
private PlayerStorage players = new PlayerStorage();
|
||||
private int world, channel;
|
||||
private ChannelServer channelServer;
|
||||
private IoAcceptor acceptor;
|
||||
private String ip, serverMessage;
|
||||
private String serverMessage;
|
||||
private MapleMapManager mapManager;
|
||||
private EventScriptManager eventSM;
|
||||
private ServicesManager services;
|
||||
@@ -121,12 +113,11 @@ public final class Channel {
|
||||
|
||||
this.ongoingStartTime = startTime + 10000; // rude approach to a world's last channel boot time, placeholder for the 1st wedding reservation ever
|
||||
this.mapManager = new MapleMapManager(null, world, channel);
|
||||
this.port = BASE_PORT + (this.channel - 1) + (world * 100);
|
||||
this.ip = YamlConfig.config.server.HOST + ":" + port;
|
||||
|
||||
try {
|
||||
port = 7575 + this.channel - 1;
|
||||
port += (world * 100);
|
||||
ip = YamlConfig.config.server.HOST + ":" + port;
|
||||
// acceptor = initAcceptor();
|
||||
channelServer = initServer(port, world, channel);
|
||||
this.channelServer = initServer(port, world, channel);
|
||||
expedType.addAll(Arrays.asList(MapleExpeditionType.values()));
|
||||
|
||||
if (Server.getInstance().isOnline()) { // postpone event loading to improve boot time... thanks Riizade, daronhudson for noticing slow startup times
|
||||
@@ -150,24 +141,12 @@ public final class Channel {
|
||||
|
||||
log.info("Channel {}: Listening on port {}", getId(), port);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.warn("Error during channel initialization", e);
|
||||
}
|
||||
}
|
||||
|
||||
private IoAcceptor initAcceptor() throws IOException {
|
||||
IoBuffer.setUseDirectBuffer(false);
|
||||
IoBuffer.setAllocator(new SimpleBufferAllocator());
|
||||
IoAcceptor acceptor = new NioSocketAcceptor();
|
||||
acceptor.setHandler(new MapleServerHandler(world, channel));
|
||||
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);
|
||||
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MapleCodecFactory()));
|
||||
acceptor.bind(new InetSocketAddress(port));
|
||||
((SocketSessionConfig) acceptor.getSessionConfig()).setTcpNoDelay(true);
|
||||
return acceptor;
|
||||
}
|
||||
|
||||
private ChannelServer initServer(int port, int world, int channel) {
|
||||
this.channelServer = new ChannelServer(port, world, channel);
|
||||
ChannelServer channelServer = new ChannelServer(port, world, channel);
|
||||
channelServer.start();
|
||||
return channelServer;
|
||||
}
|
||||
@@ -202,10 +181,8 @@ public final class Channel {
|
||||
|
||||
closeChannelSchedules();
|
||||
players = null;
|
||||
|
||||
MapleServerHandler handler = (MapleServerHandler) acceptor.getHandler();
|
||||
handler.dispose();
|
||||
acceptor.unbind();
|
||||
|
||||
channelServer.stop();
|
||||
|
||||
finishedShutdown = true;
|
||||
System.out.println("Successfully shut down Channel " + channel + " on World " + world + "\r\n");
|
||||
|
||||
@@ -295,7 +295,7 @@ public class MapleSessionCoordinator {
|
||||
client.setHwid(Hwid.fromClientString(remoteHwid));
|
||||
}
|
||||
|
||||
MapleClient fakeClient = new MapleClient(null, null, null);
|
||||
MapleClient fakeClient = MapleClient.createMock();
|
||||
Integer chrId = Server.getInstance().freeCharacteridInTransition(client);
|
||||
if (chrId != null) {
|
||||
try {
|
||||
@@ -313,15 +313,14 @@ public class MapleSessionCoordinator {
|
||||
client = fetchInTransitionSessionClient(client);
|
||||
}
|
||||
|
||||
Hwid hwid = client.getHwid();
|
||||
final Hwid hwid = client.getHwid();
|
||||
client.setHwid(null); // making sure to clean up calls to this function on login phase
|
||||
if (hwid != null) {
|
||||
onlineRemoteHwids.remove(hwid.hwid());
|
||||
}
|
||||
|
||||
String remoteHwid = client.getRemoteHwid();
|
||||
final String remoteHwid = client.getRemoteHwid();
|
||||
client.setRemoteHwid(null);
|
||||
// TODO: client.setHwid(null);
|
||||
if (remoteHwid != null) {
|
||||
onlineRemoteHwids.remove(remoteHwid);
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ public class MaplePlayerNPC extends AbstractMapleMapObject {
|
||||
World wserv = Server.getInstance().getWorld(world);
|
||||
if (wserv == null) return;
|
||||
|
||||
MapleClient c = new MapleClient(null, null, null); // mock client
|
||||
MapleClient c = MapleClient.createMock();
|
||||
c.setWorld(world);
|
||||
c.setChannel(1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user