PageRenderTime 51ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Trunk/src/net/sf/odinms/net/channel/ChannelServer.java

https://github.com/system32/NinjaMS
Java | 766 lines | 656 code | 79 blank | 31 comment | 55 complexity | 99a629139de34fdfe77affc7310a1380 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. This file is part of the OdinMS Maple Story Server
  3. Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
  4. Matthias Butz <matze@odinms.de>
  5. Jan Christian Meyer <vimes@odinms.de>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Affero General Public License version 3
  8. as published by the Free Software Foundation. You may not use, modify
  9. or distribute this program under any other version of the
  10. GNU Affero General Public License.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Affero General Public License for more details.
  15. You should have received a copy of the GNU Affero General Public License
  16. along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. package net.sf.odinms.net.channel;
  19. import java.util.logging.Level;
  20. import java.io.File;
  21. import java.io.FileNotFoundException;
  22. import java.io.FileReader;
  23. import java.io.IOException;
  24. import java.lang.management.ManagementFactory;
  25. import java.net.InetSocketAddress;
  26. import java.rmi.NotBoundException;
  27. import java.rmi.RemoteException;
  28. import java.rmi.registry.LocateRegistry;
  29. import java.rmi.registry.Registry;
  30. import java.sql.Connection;
  31. import java.sql.PreparedStatement;
  32. import java.sql.SQLException;
  33. import java.util.Collection;
  34. import java.util.Collections;
  35. import java.util.HashMap;
  36. import java.util.LinkedList;
  37. import java.util.List;
  38. import java.util.Map;
  39. import java.util.Map.Entry;
  40. import java.util.Properties;
  41. import javax.management.InstanceAlreadyExistsException;
  42. import javax.management.MBeanRegistrationException;
  43. import javax.management.MBeanServer;
  44. import javax.management.MalformedObjectNameException;
  45. import javax.management.NotCompliantMBeanException;
  46. import javax.management.ObjectName;
  47. import javax.rmi.ssl.SslRMIClientSocketFactory;
  48. import net.sf.odinms.client.MapleCharacter;
  49. import net.sf.odinms.client.NinjaMS.IRCStuff.MainIRC;
  50. import net.sf.odinms.client.NinjaMS.MapleFML;
  51. import net.sf.odinms.client.messages.CommandProcessor;
  52. import net.sf.odinms.database.DatabaseConnection;
  53. import net.sf.odinms.net.MaplePacket;
  54. import net.sf.odinms.net.MapleServerHandler;
  55. import net.sf.odinms.net.PacketProcessor;
  56. import net.sf.odinms.net.channel.OliveroMatic.AutomagicShit;
  57. import net.sf.odinms.net.channel.remote.ChannelWorldInterface;
  58. import net.sf.odinms.net.mina.MapleCodecFactory;
  59. import net.sf.odinms.net.world.MapleParty;
  60. import net.sf.odinms.net.world.MaplePartyCharacter;
  61. import net.sf.odinms.net.world.guild.MapleGuild;
  62. import net.sf.odinms.net.world.guild.MapleGuildCharacter;
  63. import net.sf.odinms.net.world.guild.MapleGuildSummary;
  64. import net.sf.odinms.net.world.remote.WorldChannelInterface;
  65. import net.sf.odinms.net.world.remote.WorldRegistry;
  66. import net.sf.odinms.provider.MapleDataProviderFactory;
  67. import net.sf.odinms.scripting.event.EventScriptManager;
  68. import net.sf.odinms.server.AutobanManager;
  69. import net.sf.odinms.server.MapleSquad;
  70. import net.sf.odinms.server.MapleSquadType;
  71. import net.sf.odinms.server.MapleTrade;
  72. import net.sf.odinms.server.ShutdownServer;
  73. import net.sf.odinms.server.TimerManager;
  74. import net.sf.odinms.server.constants.SpecialStuff;
  75. import net.sf.odinms.server.maps.MapMonitor;
  76. import net.sf.odinms.server.maps.MapleMap;
  77. import net.sf.odinms.server.maps.MapleMapFactory;
  78. import net.sf.odinms.server.quest.MapleQuest;
  79. import net.sf.odinms.tools.MaplePacketCreator;
  80. import net.sf.odinms.net.channel.storage.*;
  81. import org.apache.mina.common.ByteBuffer;
  82. import org.apache.mina.common.CloseFuture;
  83. import org.apache.mina.common.IoAcceptor;
  84. import org.apache.mina.common.SimpleByteBufferAllocator;
  85. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  86. import org.apache.mina.transport.socket.nio.SocketAcceptor;
  87. import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
  88. import org.jibble.pircbot.Colors;
  89. import org.slf4j.Logger;
  90. import org.slf4j.LoggerFactory;
  91. public class ChannelServer implements Runnable, ChannelServerMBean {
  92. private static int uniqueID = 1;
  93. private int port = 7575;
  94. private static Properties initialProp;
  95. private static final Logger log = LoggerFactory.getLogger(ChannelServer.class);
  96. private static ServerPlayerStorage serverplayerstorage = new ServerPlayerStorage();
  97. //private static ThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
  98. private static WorldRegistry worldRegistry;
  99. private PlayerStorage players = new PlayerStorage();
  100. // private Map<String, MapleCharacter> clients = new LinkedHashMap<String, MapleCharacter>();
  101. private String serverMessage;
  102. private int expRate;
  103. private int mesoRate;
  104. private int dropRate;
  105. private int bossdropRate;
  106. private int petExpRate;
  107. private boolean gmWhiteText;
  108. private boolean cashshop;
  109. private boolean dropUndroppables;
  110. private boolean moreThanOne;
  111. private int channel;
  112. private String key;
  113. private Properties props = new Properties();
  114. private ChannelWorldInterface cwi;
  115. private WorldChannelInterface wci = null;
  116. private IoAcceptor acceptor;
  117. private String ip;
  118. private boolean shutdown = false;
  119. private boolean finishedShutdown = false;
  120. private MapleMapFactory mapFactory;
  121. private EventScriptManager eventSM;
  122. private static Map<Integer, ChannelServer> instances = new HashMap<Integer, ChannelServer>();
  123. private static Map<String, ChannelServer> pendingInstances = new HashMap<String, ChannelServer>();
  124. private Map<Integer, MapleGuildSummary> gsStore = new HashMap<Integer, MapleGuildSummary>();
  125. private Boolean worldReady = true;
  126. private Map<MapleSquadType, MapleSquad> mapleSquads = new HashMap<MapleSquadType, MapleSquad>();
  127. private static boolean shuttingdown;
  128. private Map<Integer, MapMonitor> mapMonitors = new HashMap<Integer, MapMonitor>();
  129. private boolean isRebooting = false;
  130. public void addMapMonitor(int mapId, MapMonitor monitor) {
  131. mapMonitors.put(mapId, monitor);
  132. }
  133. public void removeMapMonitor(int mapId) {
  134. if (mapMonitors.containsKey(mapId)) {
  135. mapMonitors.remove(mapId);
  136. }
  137. }
  138. private ChannelServer(String key) {
  139. mapFactory = new MapleMapFactory(MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/Map.wz")), MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")));
  140. this.key = key;
  141. }
  142. public static WorldRegistry getWorldRegistry() {
  143. return worldRegistry;
  144. }
  145. public void reconnectWorld() {
  146. // check if the connection is really gone
  147. try {
  148. wci.isAvailable();
  149. } catch (RemoteException ex) {
  150. synchronized (worldReady) {
  151. worldReady = false;
  152. }
  153. synchronized (cwi) {
  154. synchronized (worldReady) {
  155. if (worldReady) {
  156. return;
  157. }
  158. }
  159. log.warn("Reconnecting to world server");
  160. synchronized (wci) {
  161. // completely re-establish the rmi connection
  162. try {
  163. initialProp = new Properties();
  164. FileReader fr = new FileReader(System.getProperty("net.sf.odinms.channel.config"));
  165. initialProp.load(fr);
  166. fr.close();
  167. Registry registry = LocateRegistry.getRegistry(initialProp.getProperty("net.sf.odinms.world.host"),
  168. Registry.REGISTRY_PORT, new SslRMIClientSocketFactory());
  169. worldRegistry = (WorldRegistry) registry.lookup("WorldRegistry");
  170. cwi = new ChannelWorldInterfaceImpl(this);
  171. wci = worldRegistry.registerChannelServer(key, cwi);
  172. props = wci.getGameProperties();
  173. expRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.exp"));
  174. mesoRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.meso"));
  175. dropRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.drop"));
  176. bossdropRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.bossdrop"));
  177. petExpRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.petExp"));
  178. dropUndroppables = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.alldrop", "false"));
  179. moreThanOne = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.morethanone", "false"));
  180. gmWhiteText = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.gmWhiteText", "false"));
  181. cashshop = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.cashshop", "false"));
  182. Properties dbProp = new Properties();
  183. fr = new FileReader("db.properties");
  184. dbProp.load(fr);
  185. fr.close();
  186. DatabaseConnection.setProps(dbProp);
  187. DatabaseConnection.getConnection();
  188. wci.serverReady();
  189. } catch (Exception e) {
  190. log.error("Reconnecting failed", e);
  191. }
  192. worldReady = true;
  193. }
  194. }
  195. synchronized (worldReady) {
  196. worldReady.notifyAll();
  197. }
  198. }
  199. }
  200. @Override
  201. public void run() {
  202. try {
  203. cwi = new ChannelWorldInterfaceImpl(this);
  204. wci = worldRegistry.registerChannelServer(key, cwi);
  205. props = wci.getGameProperties();
  206. expRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.exp"));
  207. mesoRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.meso"));
  208. dropRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.drop"));
  209. bossdropRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.bossdrop"));
  210. petExpRate = Integer.parseInt(props.getProperty("net.sf.odinms.world.petExp"));
  211. dropUndroppables = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.alldrop", "false"));
  212. moreThanOne = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.morethanone", "false"));
  213. eventSM = new EventScriptManager(this, props.getProperty("net.sf.odinms.channel.events").split(","));
  214. gmWhiteText = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.gmWhiteText", "false"));
  215. cashshop = Boolean.parseBoolean(props.getProperty("net.sf.odinms.world.cashshop", "false"));
  216. Properties dbProp = new Properties();
  217. FileReader fileReader = new FileReader("db.properties");
  218. dbProp.load(fileReader);
  219. fileReader.close();
  220. DatabaseConnection.setProps(dbProp);
  221. DatabaseConnection.getConnection();
  222. // MapleShopFactory.getInstance().loadAllShops();
  223. try {
  224. Connection con = DatabaseConnection.getConnection();
  225. PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = 0");
  226. ps.executeUpdate();
  227. ps.close();
  228. ps = con.prepareStatement("UPDATE characters SET mutality = 0");
  229. ps.executeUpdate();
  230. ps.close();
  231. } catch (SQLException ex) {
  232. System.err.println("Could not reset databases loggedin state" + ex);
  233. }
  234. } catch (Exception e) {
  235. throw new RuntimeException(e);
  236. }
  237. port = Integer.parseInt(props.getProperty("net.sf.odinms.channel.net.port"));
  238. ip = props.getProperty("net.sf.odinms.channel.net.interface") + ":" + port;
  239. ByteBuffer.setUseDirectBuffers(false);
  240. ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
  241. acceptor = new SocketAcceptor();
  242. SocketAcceptorConfig cfg = new SocketAcceptorConfig();
  243. // cfg.setThreadModel(ThreadModel.MANUAL); // *fingers crossed*, I hope the executor filter handles everything
  244. // executor = new ThreadPoolExecutor(16, 16, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
  245. // cfg.getFilterChain().addLast("executor", new ExecutorFilter(executor));
  246. cfg.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MapleCodecFactory()));
  247. cfg.getSessionConfig().setTcpNoDelay(true);
  248. // Item.loadInitialDataFromDB();
  249. TimerManager tMan = TimerManager.getInstance();
  250. tMan.start();
  251. tMan.register(AutobanManager.getInstance(), 60000);
  252. setServerMessage();
  253. if (channel == 1) {
  254. AutomagicShit.getInstance().start();
  255. }
  256. if (channel == 9) {
  257. sendIRCNotice();
  258. }
  259. tMan.register(new spawnMobs(), 10000);
  260. tMan.register(new autoSave(), 5 * 1000 * 60 * Integer.parseInt(initialProp.getProperty("net.sf.odinms.channel.count")), 10 * 1000 * 60 * (channel - 1) + (60000));
  261. try {
  262. MapleServerHandler serverHandler = new MapleServerHandler(PacketProcessor.getProcessor(PacketProcessor.Mode.CHANNELSERVER), channel);
  263. acceptor.bind(new InetSocketAddress(port), serverHandler, cfg);
  264. log.info("Channel {}: Listening on port {}", getChannel(), port);
  265. wci.serverReady();
  266. eventSM.init();
  267. } catch (IOException e) {
  268. log.error("Binding to port " + port + " failed (ch: " + getChannel() + ")", e);
  269. }
  270. }
  271. public void shutdown() {
  272. // dc all clients by hand so we get sessionClosed...
  273. shutdown = true;
  274. List<CloseFuture> futures = new LinkedList<CloseFuture>();
  275. Collection<MapleCharacter> allchars = players.getAllCharacters();
  276. MapleCharacter chrs[] = allchars.toArray(new MapleCharacter[allchars.size()]);
  277. for (MapleCharacter chr : chrs) {
  278. if (chr.getTrade() != null) {
  279. MapleTrade.cancelTrade(chr);
  280. }
  281. if (chr.getEventInstance() != null) {
  282. chr.getEventInstance().playerDisconnected(chr);
  283. }
  284. chr.forceSave(true, true);
  285. if (chr.getCheatTracker() != null) {
  286. chr.getCheatTracker().dispose();
  287. }
  288. removePlayer(chr);
  289. }
  290. for (MapleCharacter chr : chrs) {
  291. futures.add(chr.getClient().getSession().close());
  292. }
  293. for (CloseFuture future : futures) {
  294. future.join(500);
  295. }
  296. try {
  297. getWorldRegistry().deregisterChannelServer(channel);
  298. } catch (RemoteException ex) {
  299. java.util.logging.Logger.getLogger(ChannelServer.class.getName()).log(Level.SEVERE, null, ex);
  300. }
  301. finishedShutdown = true;
  302. wci = null;
  303. cwi = null;
  304. }
  305. public void unbind() {
  306. acceptor.unbindAll();
  307. }
  308. public boolean hasFinishedShutdown() {
  309. return finishedShutdown;
  310. }
  311. public MapleMapFactory getMapFactory() {
  312. return mapFactory;
  313. }
  314. public static ChannelServer newInstance(String key) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException {
  315. ChannelServer instance = new ChannelServer(key);
  316. MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
  317. mBeanServer.registerMBean(instance, new ObjectName("net.sf.odinms.net.channel:type=ChannelServer,name=ChannelServer" + uniqueID++));
  318. pendingInstances.put(key, instance);
  319. return instance;
  320. }
  321. public static ChannelServer getInstance(int channel) {
  322. return instances.get(channel);
  323. }
  324. public void addPlayer(MapleCharacter chr) {
  325. players.registerPlayer(chr);
  326. chr.getClient().getSession().write(MaplePacketCreator.serverMessage(serverMessage));
  327. }
  328. public IPlayerStorage getPlayerStorage() {
  329. return players;
  330. }
  331. public void removePlayer(MapleCharacter chr) {
  332. players.deregisterPlayer(chr);
  333. }
  334. public int getConnectedClients() {
  335. return players.getAllCharacters().size();
  336. }
  337. @Override
  338. public String getServerMessage() {
  339. return serverMessage;
  340. }
  341. @Override
  342. public void setServerMessage(String newMessage) {
  343. serverMessage = newMessage;
  344. broadcastPacket(MaplePacketCreator.serverMessage(serverMessage));
  345. }
  346. public void setServerMessage() {
  347. try {
  348. serverMessage = getWorldInterface().getArrayString();
  349. } catch (RemoteException ex) {
  350. java.util.logging.Logger.getLogger(ChannelServer.class.getName()).log(Level.SEVERE, null, ex);
  351. }
  352. }
  353. public void broadcastPacket(MaplePacket data) {
  354. for (MapleCharacter chr : players.getAllCharacters()) {
  355. chr.getClient().getSession().write(data);
  356. }
  357. }
  358. @Override
  359. public int getExpRate() {
  360. return expRate;
  361. }
  362. @Override
  363. public void setExpRate(int expRate) {
  364. this.expRate = expRate;
  365. }
  366. public int getChannel() {
  367. return channel;
  368. }
  369. public void setChannel(int channel) {
  370. if (pendingInstances.containsKey(key)) {
  371. pendingInstances.remove(key);
  372. }
  373. if (instances.containsKey(channel)) {
  374. instances.remove(channel);
  375. }
  376. instances.put(channel, this);
  377. this.channel = channel;
  378. this.mapFactory.setChannel(channel);
  379. }
  380. public static Collection<ChannelServer> getAllInstances() {
  381. return Collections.unmodifiableCollection(instances.values());
  382. }
  383. public String getIP() {
  384. return ip;
  385. }
  386. public String getIP(int channel) {
  387. try {
  388. return getWorldInterface().getIP(channel);
  389. } catch (RemoteException e) {
  390. log.error("Lost connection to world server", e);
  391. throw new RuntimeException("Lost connection to world server");
  392. }
  393. }
  394. public WorldChannelInterface getWorldInterface() {
  395. synchronized (worldReady) {
  396. while (!worldReady) {
  397. try {
  398. worldReady.wait();
  399. } catch (InterruptedException ignored) {
  400. }
  401. }
  402. }
  403. return wci;
  404. }
  405. public String getProperty(String name) {
  406. return props.getProperty(name);
  407. }
  408. public boolean isShutdown() {
  409. return shutdown;
  410. }
  411. @Override
  412. public void shutdown(int time) {
  413. broadcastPacket(MaplePacketCreator.serverNotice(0, "The world will be shut down in " + (time / 60000) + " minutes, please log off safely"));
  414. TimerManager.getInstance().schedule(new ShutdownServer(getChannel()), time);
  415. }
  416. @Override
  417. public void shutdownWorld(int time) {
  418. try {
  419. getWorldInterface().shutdown(time);
  420. } catch (RemoteException e) {
  421. reconnectWorld();
  422. }
  423. }
  424. public int getLoadedMaps() {
  425. return mapFactory.getLoadedMaps();
  426. }
  427. public EventScriptManager getEventSM() {
  428. return eventSM;
  429. }
  430. public void reloadEvents() {
  431. eventSM.cancel();
  432. eventSM = new EventScriptManager(this, props.getProperty("net.sf.odinms.channel.events").split(","));
  433. eventSM.init();
  434. }
  435. @Override
  436. public int getMesoRate() {
  437. return mesoRate;
  438. }
  439. @Override
  440. public void setMesoRate(int mesoRate) {
  441. this.mesoRate = mesoRate;
  442. }
  443. @Override
  444. public int getDropRate() {
  445. return dropRate;
  446. }
  447. @Override
  448. public void setDropRate(int dropRate) {
  449. this.dropRate = dropRate;
  450. }
  451. @Override
  452. public int getBossDropRate() {
  453. return bossdropRate;
  454. }
  455. @Override
  456. public void setBossDropRate(int bossdropRate) {
  457. this.bossdropRate = bossdropRate;
  458. }
  459. @Override
  460. public int getPetExpRate() {
  461. return petExpRate;
  462. }
  463. @Override
  464. public void setPetExpRate(int petExpRate) {
  465. this.petExpRate = petExpRate;
  466. }
  467. public boolean allowUndroppablesDrop() {
  468. return dropUndroppables;
  469. }
  470. public boolean allowMoreThanOne() {
  471. return moreThanOne;
  472. }
  473. public boolean allowGmWhiteText() {
  474. return gmWhiteText;
  475. }
  476. public boolean allowCashshop() {
  477. return cashshop;
  478. }
  479. public MapleGuild getGuild(MapleGuildCharacter mgc) {
  480. int gid = mgc.getGuildId();
  481. MapleGuild g = null;
  482. try {
  483. g = this.getWorldInterface().getGuild(gid, mgc);
  484. } catch (RemoteException re) {
  485. log.error("RemoteException while fetching MapleGuild.", re);
  486. return null;
  487. }
  488. if (gsStore.get(gid) == null) {
  489. gsStore.put(gid, new MapleGuildSummary(g));
  490. }
  491. return g;
  492. }
  493. public MapleGuildSummary getGuildSummary(int gid) {
  494. if (gsStore.containsKey(gid)) {
  495. return gsStore.get(gid);
  496. } else { //this shouldn't happen much, if ever, but if we're caught
  497. //without the summary, we'll have to do a worldop
  498. try {
  499. MapleGuild g = this.getWorldInterface().getGuild(gid, null);
  500. if (g != null) {
  501. gsStore.put(gid, new MapleGuildSummary(g));
  502. }
  503. return gsStore.get(gid); //if g is null, we will end up returning null
  504. } catch (RemoteException re) {
  505. log.error("RemoteException while fetching GuildSummary.", re);
  506. return null;
  507. }
  508. }
  509. }
  510. public void updateGuildSummary(int gid, MapleGuildSummary mgs) {
  511. gsStore.put(gid, mgs);
  512. }
  513. public void reloadGuildSummary() {
  514. try {
  515. MapleGuild g;
  516. for (int i : gsStore.keySet()) {
  517. g = this.getWorldInterface().getGuild(i, null);
  518. if (g != null) {
  519. gsStore.put(i, new MapleGuildSummary(g));
  520. } else {
  521. gsStore.remove(i);
  522. }
  523. }
  524. } catch (RemoteException re) {
  525. log.error("RemoteException while reloading GuildSummary.", re);
  526. }
  527. }
  528. public static void main(String args[]) throws FileNotFoundException, IOException, NotBoundException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException {
  529. initialProp = new Properties();
  530. initialProp.load(new FileReader(System.getProperty("net.sf.odinms.channel.config")));
  531. Registry registry = LocateRegistry.getRegistry(initialProp.getProperty("net.sf.odinms.world.host"), Registry.REGISTRY_PORT, new SslRMIClientSocketFactory());
  532. worldRegistry = (WorldRegistry) registry.lookup("WorldRegistry");
  533. for (int i = 0; i < Integer.parseInt(initialProp.getProperty("net.sf.odinms.channel.count", "0")); i++) {
  534. newInstance(initialProp.getProperty("net.sf.odinms.channel." + i + ".key")).run();
  535. }
  536. DatabaseConnection.getConnection(); // touch - so we see database problems early...
  537. CommandProcessor.registerMBean();
  538. MapleQuest.getAllQuests();
  539. SpecialStuff.getInstance();
  540. MainIRC.getInstance();
  541. }
  542. public MapleSquad getMapleSquad(MapleSquadType type) {
  543. return mapleSquads.get(type);
  544. }
  545. public boolean addMapleSquad(MapleSquad squad, MapleSquadType type) {
  546. if (mapleSquads.get(type) == null) {
  547. mapleSquads.remove(type);
  548. mapleSquads.put(type, squad);
  549. return true;
  550. } else {
  551. return false;
  552. }
  553. }
  554. public boolean removeMapleSquad(MapleSquad squad, MapleSquadType type) {
  555. if (mapleSquads.containsKey(type)) {
  556. if (mapleSquads.get(type) == squad) {
  557. mapleSquads.remove(type);
  558. return true;
  559. }
  560. }
  561. return false;
  562. }
  563. public static boolean isShuttingDown() {
  564. return shuttingdown;
  565. }
  566. public void setShuttingDown(boolean fuck) {
  567. shuttingdown = fuck;
  568. }
  569. public void broadcastGMPacket(MaplePacket data) {
  570. for (MapleCharacter chr : players.getAllCharacters()) {
  571. if (chr.isJounin()) {
  572. chr.getClient().getSession().write(data);
  573. }
  574. }
  575. }
  576. public void broadcastStaffPacket(MaplePacket data) {
  577. for (MapleCharacter chr : players.getAllCharacters()) {
  578. if (chr.isChunin()) {
  579. chr.getClient().getSession().write(data);
  580. }
  581. }
  582. }
  583. private class spawnMobs implements Runnable {
  584. @Override
  585. public void run() {
  586. for (Entry<Integer, MapleMap> map : mapFactory.getMaps().entrySet()) {
  587. if (map.getValue() == null) {
  588. log.error("Channel " + getChannel() + " mob factory failed to load " + map.getValue().getMapName() + " (" + map.getValue().getId() + ").");
  589. map.getValue().deleteAndReloadMap();
  590. continue;
  591. }
  592. map.getValue().respawn();
  593. }
  594. }
  595. }
  596. private class autoSave implements Runnable {
  597. @Override
  598. public void run() {
  599. int i = 0;
  600. for (final MapleCharacter lols : getPlayerStorage().getAllCharacters()) {
  601. i++;
  602. TimerManager.getInstance().schedule(new Runnable() {
  603. @Override
  604. public void run() {
  605. if (lols != null) {
  606. lols.runAutoSave();
  607. lols.dropMessage(5, "Your Progress Has been saved AutoMagically.");
  608. }
  609. }
  610. }, i * 1000);
  611. }
  612. log.info("Saving characters to database for channel " + channel);
  613. }
  614. }
  615. public boolean isIsRebooting() {
  616. return isRebooting;
  617. }
  618. public void setIsRebooting(boolean isRebooting) {
  619. this.isRebooting = isRebooting;
  620. }
  621. public void scheduleReboot(){
  622. this.isRebooting = true;
  623. int i = this.channel;
  624. for (ChannelServer cserv : getAllInstances()) {
  625. cserv.broadcastPacket(MaplePacketCreator.serverNotice(6, "The Channel Is Now Rebooting in 30 seconds. Please CC safely to avoid problems"));
  626. }
  627. TimerManager.getInstance().schedule(new scheduleReboot(), 30 * 1000);
  628. }
  629. private class scheduleReboot implements Runnable {
  630. final int i = channel;
  631. @Override
  632. public void run() {
  633. instances.get(i).shutdown();
  634. instances.remove(i);
  635. log.info("Channel "+i+"Shut Down");
  636. try {
  637. newInstance(initialProp.getProperty("net.sf.odinms.channel." + i + ".key")).run();
  638. } catch (InstanceAlreadyExistsException ex) {
  639. java.util.logging.Logger.getLogger(ChannelServer.class.getName()).log(Level.SEVERE, null, ex);
  640. } catch (MBeanRegistrationException ex) {
  641. java.util.logging.Logger.getLogger(ChannelServer.class.getName()).log(Level.SEVERE, null, ex);
  642. } catch (NotCompliantMBeanException ex) {
  643. java.util.logging.Logger.getLogger(ChannelServer.class.getName()).log(Level.SEVERE, null, ex);
  644. } catch (MalformedObjectNameException ex) {
  645. java.util.logging.Logger.getLogger(ChannelServer.class.getName()).log(Level.SEVERE, null, ex);
  646. }
  647. log.info("Channel "+i+"Rebooted");
  648. }
  649. }
  650. public void restarttimers() {
  651. TimerManager tMan = TimerManager.getInstance();
  652. tMan.start();
  653. tMan.register(AutobanManager.getInstance(), 60000);
  654. tMan.register(new spawnMobs(), 10000);
  655. tMan.register(new autoSave(), 5 * 1000 * 60 * Integer.parseInt(initialProp.getProperty("net.sf.odinms.channel.count")), 10 * 1000 * 60 * (channel - 1) + (60000));
  656. }
  657. private void sendIRCNotice() {
  658. MainIRC.getInstance().sendGlobalMessage(Colors.DARK_GREEN + Colors.REVERSE + "The Server Is Up. See you in game");
  659. MainIRC.getInstance().sendGlobalMessage("******************************************************************************** ");
  660. }
  661. public void yellowWorldMessage(String msg) {
  662. for (MapleCharacter mc : getPlayerStorage().getAllCharacters()) {
  663. mc.getClient().getSession().write(MaplePacketCreator.sendYellowTip(msg));
  664. }
  665. if (channel == 1) {
  666. MainIRC.getInstance().sendIrcMessage("# Ninja Tip :" + msg);
  667. }
  668. }
  669. public List<MapleCharacter> getPartyMembers(MapleParty party) {
  670. List<MapleCharacter> partym = new LinkedList<MapleCharacter>();
  671. for (MaplePartyCharacter partychar : party.getMembers()) {
  672. if (partychar.getChannel() == getChannel()) { // Make sure the thing doesn't get duplicate plays due to ccing bug.
  673. MapleCharacter chr = getPlayerStorage().getCharacterByName(partychar.getName());
  674. if (chr != null) {
  675. partym.add(chr);
  676. }
  677. }
  678. }
  679. return partym;
  680. }
  681. public static ServerPlayerStorage getServerPlayerStorage() {
  682. return serverplayerstorage;
  683. }
  684. }