package handling.channel; import clientside.MapleCharacter; import constants.GameConstants; import handling.MapleServerHandler; import handling.cashshop.CashShopServer; import handling.login.LoginServer; import handling.mina.MapleCodecFactory; import handling.world.MaplePartyCharacter; import java.io.IOException; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import scripting.EventScriptManager; import server.MapleSquad; import server.ServerProperties; import server.Start; import server.life.PlayerNPC; import server.maps.AramiaFireWorks; import server.maps.MapleMapFactory; import server.maps.MapleMapObject; import server.shops.HiredMerchant; import tools.ConcurrentEnumMap; import tools.packet.CWvsContext; //import server.events.MapleEventType; public class ChannelServer { public static long serverStartTime; private int expRate; private int mesoRate; private int dropRate = 2; private int cashRate = 1; private int traitRate = 3; private int BossDropRate = 1; private short port = 8585; private static final short DEFAULT_PORT = 8585; private int channel; private int running_MerchantID = 0; private int flags = 0; private String serverMessage; private String ip; private String serverName; private boolean shutdown = false; private boolean finishedShutdown = false; private boolean MegaphoneMuteState = false; private boolean adminOnly = false; private PlayerStorage players; private IoAcceptor acceptor; private final MapleMapFactory mapFactory; private EventScriptManager eventSM; private AramiaFireWorks works = new AramiaFireWorks(); private static final Map<Integer, ChannelServer> instances = new HashMap(); private final Map<MapleSquad.MapleSquadType, MapleSquad> mapleSquads = new ConcurrentEnumMap(MapleSquad.MapleSquadType.class); private final Map<Integer, HiredMerchant> merchants = new HashMap(); private final List<PlayerNPC> playerNPCs = new LinkedList(); private final ReentrantReadWriteLock merchLock = new ReentrantReadWriteLock(); private int eventmap = -1; // private final Map<MapleEventType, MapleEvent> events = new EnumMap<MapleEventType, MapleEvent>(MapleEventType.class); public boolean eventOn = false; public int eventMap = 0; private boolean eventWarp; private String eventHost; private String eventName; // private final Map<MapleEventType, MapleEvent> events = new EnumMap<>(MapleEventType.class); private ChannelServer(int channel) { this.channel = channel; this.mapFactory = new MapleMapFactory(channel); } public static Set<Integer> getAllInstance() { return new HashSet(instances.keySet()); } public final void run_startup_configurations() { setChannel(this.channel); try { this.expRate = Integer.parseInt(ServerProperties.getProperty("net.sf.odinms.world.exp")); this.mesoRate = Integer.parseInt(ServerProperties.getProperty("net.sf.odinms.world.meso")); this.serverMessage = ServerProperties.getProperty("net.sf.odinms.world.serverMessage"); this.serverName = ServerProperties.getProperty("net.sf.odinms.login.serverName"); this.flags = Integer.parseInt(ServerProperties.getProperty("net.sf.odinms.world.flags", "0")); this.eventSM = new EventScriptManager(this, ServerProperties.getProperty("net.sf.odinms.channel.events").split(",")); this.port = Short.parseShort(ServerProperties.getProperty("net.sf.odinms.channel.net.port" + this.channel, String.valueOf(8585 + this.channel))); } catch (Exception e) { throw new RuntimeException(e); } this.ip = (Start.nexonip + ":" + this.port); IoBuffer.setUseDirectBuffer(false); IoBuffer.setAllocator(new SimpleBufferAllocator()); acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast("codec", (IoFilter) new ProtocolCodecFilter(new MapleCodecFactory())); players = new PlayerStorage(channel); try { acceptor.setHandler(new MapleServerHandler(channel, false, false)); acceptor.bind(new InetSocketAddress(port)); ((SocketSessionConfig) acceptor.getSessionConfig()).setTcpNoDelay(true); System.out.println("Channel " + this.channel + ": Listening on port " + this.port + ""); this.eventSM.init(); } catch (IOException e) { System.out.println("Binding to port " + this.port + " failed (ch: " + getChannel() + ")" + e); } } public final void shutdown() { if (this.finishedShutdown) { return; } broadcastPacket(CWvsContext.serverNotice(0, "This channel will now shut down.")); this.shutdown = true; System.out.println("Channel " + this.channel + ", Saving characters..."); getPlayerStorage().disconnectAll(); acceptor.setCloseOnDeactivation(true); for (IoSession ss : acceptor.getManagedSessions().values()) { ss.close(true); } acceptor.unbind(); acceptor.dispose(); System.out.println("Channel " + this.channel + ", Unbinding..."); instances.remove(Integer.valueOf(this.channel)); setFinishShutdown(); } public final MapleCharacter getPlayer() { return getPlayer(); } public final List<MapleCharacter> getPartyMembers(MapleCharacter party) { List chars = new LinkedList(); for (MaplePartyCharacter partychar : getPlayer().getParty().getMembers()) { if (partychar.getChannel() == getChannel()) { MapleCharacter chr = getPlayerStorage().getCharacterByName(partychar.getName()); if (chr != null) { chars.add(chr); } } } return chars; } public final boolean hasFinishedShutdown() { return this.finishedShutdown; } public final MapleMapFactory getMapFactory() { return this.mapFactory; } public static final ChannelServer newInstance(int channel) { return new ChannelServer(channel); } public static final ChannelServer getInstance(int channel) { return (ChannelServer) instances.get(Integer.valueOf(channel)); } public final void addPlayer(MapleCharacter chr) { getPlayerStorage().registerPlayer(chr); } public PlayerStorage getPlayerStorage() { if (players == null) { //wth players = new PlayerStorage(channel); //wthhhh } return players; } public final void removePlayer(MapleCharacter chr) { getPlayerStorage().deregisterPlayer(chr); } public final void removePlayer(int idz, String namez) { getPlayerStorage().deregisterPlayer(idz, namez); } public final String getServerMessage() { return this.serverMessage; } public final void setServerMessage(String newMessage) { this.serverMessage = newMessage; broadcastPacket(CWvsContext.serverMessage(this.serverMessage)); } public final void broadcastPacket(byte[] data) { getPlayerStorage().broadcastPacket(data); } public final void broadcastSmegaPacket(byte[] data) { getPlayerStorage().broadcastSmegaPacket(data); } public final void broadcastGMPacket(byte[] data) { getPlayerStorage().broadcastGMPacket(data); } public final int getExpRate() { return this.expRate; } public final void setExpRate(int expRate) { this.expRate = expRate; } public final int getCashRate() { return this.cashRate; } public final int getChannel() { return this.channel; } public final void setChannel(int channel) { instances.put(Integer.valueOf(channel), this); LoginServer.addChannel(channel); } public static final ArrayList<ChannelServer> getAllInstances() { return new ArrayList(instances.values()); } public final String getIP() { return this.ip; } public String getIP(int channel) { try { return getIP(channel); } catch (Exception e) { System.out.println("Lost connection to world server " + e); } throw new RuntimeException("Lost connection to world server"); } public final boolean isShutdown() { return this.shutdown; } public final int getLoadedMaps() { return this.mapFactory.getLoadedMaps(); } public final EventScriptManager getEventSM() { return this.eventSM; } public final void reloadEvents() { this.eventSM.cancel(); this.eventSM = new EventScriptManager(this, ServerProperties.getProperty("net.sf.odinms.channel.events").split(",")); this.eventSM.init(); } public final int getMesoRate() { return this.mesoRate; } public final void setMesoRate(int mesoRate) { this.mesoRate = mesoRate; } public final int getDropRate() { return this.dropRate; } public final int getBossDropRate() { return this.BossDropRate; } public static final void startChannel_Main() { serverStartTime = System.currentTimeMillis(); for (int i = 0; i < Integer.parseInt(ServerProperties.getProperty("net.sf.odinms.channel.count", "0")); i++) { newInstance(i + 1).run_startup_configurations(); } } public Map<MapleSquad.MapleSquadType, MapleSquad> getAllSquads() { return Collections.unmodifiableMap(this.mapleSquads); } public final MapleSquad getMapleSquad(String type) { return getMapleSquad(MapleSquad.MapleSquadType.valueOf(type.toLowerCase())); } public final MapleSquad getMapleSquad(MapleSquad.MapleSquadType type) { return (MapleSquad) this.mapleSquads.get(type); } public final boolean addMapleSquad(MapleSquad squad, String type) { MapleSquad.MapleSquadType types = MapleSquad.MapleSquadType.valueOf(type.toLowerCase()); if ((types != null) && (!this.mapleSquads.containsKey(types))) { this.mapleSquads.put(types, squad); squad.scheduleRemoval(); return true; } return false; } public final boolean removeMapleSquad(MapleSquad.MapleSquadType types) { if ((types != null) && (this.mapleSquads.containsKey(types))) { this.mapleSquads.remove(types); return true; } return false; } public final int closeAllMerchant() { int ret = 0; this.merchLock.writeLock().lock(); try { Iterator merchants_ = this.merchants.entrySet().iterator(); while (merchants_.hasNext()) { HiredMerchant hm = (HiredMerchant) ((Map.Entry) merchants_.next()).getValue(); hm.closeShop(true, false); hm.getMap().removeMapObject(hm); merchants_.remove(); ret++; } } finally { this.merchLock.writeLock().unlock(); } for (int i = 910000001; i <= 910000022; i++) { for (MapleMapObject mmo : this.mapFactory.getMap(i).getAllHiredMerchantsThreadsafe()) { ((HiredMerchant) mmo).closeShop(true, false); ret++; } } return ret; } public final int addMerchant(HiredMerchant hMerchant) { this.merchLock.writeLock().lock(); try { this.running_MerchantID += 1; this.merchants.put(Integer.valueOf(this.running_MerchantID), hMerchant); return this.running_MerchantID; } finally { this.merchLock.writeLock().unlock(); } } public final void removeMerchant(HiredMerchant hMerchant) { this.merchLock.writeLock().lock(); try { this.merchants.remove(Integer.valueOf(hMerchant.getStoreId())); } finally { this.merchLock.writeLock().unlock(); } } public final boolean containsMerchant(int accid, int cid) { boolean contains = false; this.merchLock.readLock().lock(); try { Iterator itr = this.merchants.values().iterator(); while (itr.hasNext()) { HiredMerchant hm = (HiredMerchant) itr.next(); if ((hm.getOwnerAccId() == accid) || (hm.getOwnerId() == cid)) { contains = true; break; } } } finally { this.merchLock.readLock().unlock(); } return contains; } public final List<HiredMerchant> searchMerchant(int itemSearch) { List list = new LinkedList(); this.merchLock.readLock().lock(); try { Iterator itr = this.merchants.values().iterator(); while (itr.hasNext()) { HiredMerchant hm = (HiredMerchant) itr.next(); if (hm.searchItem(itemSearch).size() > 0) { list.add(hm); } } } finally { this.merchLock.readLock().unlock(); } return list; } public final void toggleMegaphoneMuteState() { this.MegaphoneMuteState = (!this.MegaphoneMuteState); } public final boolean getMegaphoneMuteState() { return this.MegaphoneMuteState; } public final Collection<PlayerNPC> getAllPlayerNPC() { return this.playerNPCs; } public final void addPlayerNPC(PlayerNPC npc) { if (this.playerNPCs.contains(npc)) { return; } this.playerNPCs.add(npc); getMapFactory().getMap(npc.getMapId()).addMapObject(npc); } public final void removePlayerNPC(PlayerNPC npc) { if (this.playerNPCs.contains(npc)) { this.playerNPCs.remove(npc); getMapFactory().getMap(npc.getMapId()).removeMapObject(npc); } } public final String getServerName() { return this.serverName; } public final void setServerName(String sn) { this.serverName = sn; } public final String getTrueServerName() { return this.serverName.substring(0, this.serverName.length() - (GameConstants.GMS ? 2 : 3)); } public final int getPort() { return this.port; } public static final Set<Integer> getChannelServer() { return new HashSet(instances.keySet()); } public final void setShutdown() { this.shutdown = true; System.out.println("Channel " + this.channel + " has set to shutdown and is closing Hired Merchants..."); } public final void setFinishShutdown() { this.finishedShutdown = true; System.out.println("Channel " + this.channel + " has finished shutdown."); } public final boolean isAdminOnly() { return this.adminOnly; } public static final int getChannelCount() { return instances.size(); } public final int getTempFlag() { return this.flags; } public static Map<Integer, Integer> getChannelLoad() { Map ret = new HashMap(); for (ChannelServer cs : instances.values()) { ret.put(Integer.valueOf(cs.getChannel()), Integer.valueOf(cs.getConnectedClients())); } return ret; } public int getConnectedClients() { return getPlayerStorage().getConnectedClients(); } public void broadcastMessage(byte[] message) { broadcastPacket(message); } public void broadcastSmega(byte[] message) { broadcastSmegaPacket(message); } public void broadcastGMMessage(byte[] message) { broadcastGMPacket(message); } public AramiaFireWorks getFireWorks() { return this.works; } public int getTraitRate() { return this.traitRate; } }