001/* 002 * Trident - A Multithreaded Server Alternative 003 * Copyright 2014 The TridentSDK Team 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package net.tridentsdk.server; 019 020import net.tridentsdk.*; 021import net.tridentsdk.config.Config; 022import net.tridentsdk.entity.living.Player; 023import net.tridentsdk.plugin.Plugin; 024import net.tridentsdk.registry.Registered; 025import net.tridentsdk.server.command.TridentConsole; 026import net.tridentsdk.server.concurrent.ConcurrentTaskExecutor; 027import net.tridentsdk.server.concurrent.MainThread; 028import net.tridentsdk.server.concurrent.ThreadsHandler; 029import net.tridentsdk.server.concurrent.TridentTaskScheduler; 030import net.tridentsdk.server.netty.protocol.Protocol; 031import net.tridentsdk.server.player.TridentPlayer; 032import net.tridentsdk.server.service.Statuses; 033import net.tridentsdk.server.world.TridentWorld; 034import net.tridentsdk.server.world.TridentWorldLoader; 035import net.tridentsdk.util.TridentLogger; 036import net.tridentsdk.world.World; 037 038import javax.annotation.concurrent.ThreadSafe; 039import java.io.IOException; 040import java.net.InetAddress; 041 042/** 043 * The access base to internal workings of the server 044 * 045 * @author The TridentSDK Team 046 */ 047@ThreadSafe 048public final class TridentServer implements Server { 049 // TODO this is temporary for testing 050 public static TridentWorld WORLD; 051 private final MainThread mainThread; 052 053 private final Config config; 054 private final Protocol protocol; 055 private final TridentLogger logger; 056 057 private final TridentConsole console; 058 059 final TridentWorldLoader rootWorldLoader; 060 private volatile PingInfo pingInfo; 061 062 private TridentServer(Config config) { 063 this.config = config; 064 this.protocol = new Protocol(); 065 this.logger = TridentLogger.get(getClass()); 066 this.mainThread = new MainThread(20); 067 this.rootWorldLoader = new TridentWorldLoader(); 068 this.console = new TridentConsole(); 069 this.pingInfo = new PingInfo(); 070 } 071 072 /** 073 * Creates the server access base, distributing information to the fields available 074 * 075 * @param config the configuration to use for option lookup 076 */ 077 public static TridentServer createServer(Config config) { 078 TridentServer server = new TridentServer(config); 079 Trident.setServer(server); 080 server.mainThread.start(); 081 return server; 082 // We CANNOT let the "this" instance escape during creation, else we lose thread-safety 083 } 084 085 /** 086 * Gets the instance of the server 087 * 088 * @return the server singleton 089 */ 090 public static TridentServer instance() { 091 return (TridentServer) Trident.instance(); 092 } 093 094 /** 095 * Get the protocol base of the server 096 * 097 * @return the access to server protocol 098 */ 099 public Protocol protocol() { 100 return this.protocol; 101 } 102 103 public int compressionThreshold() { 104 return this.config.getInt("compression-threshold", Defaults.COMPRESSION_THRESHOLD); 105 } 106 107 public MainThread mainThread() { 108 return mainThread; 109 } 110 111 @Override 112 public Console console() { 113 return console; 114 } 115 116 /** 117 * Gets the port the server currently runs on 118 * 119 * @return the port occupied by the server 120 */ 121 @Override 122 public int port() { 123 return this.config.getInt("port", 25565); 124 } 125 126 @Override 127 public Config config() { 128 return this.config; 129 } 130 131 /** 132 * Performs the shutdown procedure on the server, ending with the exit of the JVM 133 */ 134 @Override 135 public void shutdown() { 136 try { 137 TridentLogger.get().log("Saving files..."); 138 try { 139 ((Statuses) Registered.statuses()).saveAll(); 140 } catch (IOException e) { 141 e.printStackTrace(); 142 } 143 144 TridentLogger.get().log("Kicking players..."); 145 for (Player player : TridentPlayer.players()) { 146 ((TridentPlayer) player).kickPlayer("Server shutting down"); 147 ((TridentPlayer) player).connection().logout(); 148 } 149 150 TridentLogger.get().log("Saving worlds..."); 151 for (World world : rootWorldLoader.worlds()) 152 ((TridentWorld) world).save(); 153 154 TridentLogger.get().log("Shutting down scheduler..."); 155 ((TridentTaskScheduler) Registered.tasks()).shutdown(); 156 157 TridentLogger.get().log("Shutting down server process..."); 158 ThreadsHandler.shutdownAll(); 159 160 //TODO: Cleanup stuff... 161 TridentLogger.get().log("Shutting down plugins..."); 162 for (Plugin plugin : Registered.plugins()) 163 Registered.plugins().disable(plugin); 164 165 TridentLogger.get().log("Shutting down thread pools..."); 166 ConcurrentTaskExecutor.executors().forEach(ConcurrentTaskExecutor::shutdown); 167 168 TridentLogger.get().log("Shutting down server connections..."); 169 TridentStart.close(); 170 } catch (Exception e) { 171 TridentLogger.get().error("Server failed to shutdown correctly"); 172 TridentLogger.get().error(e); 173 return; 174 } 175 176 TridentLogger.get().log("Server shutdown successfully."); 177 } 178 179 @Override 180 public InetAddress ip() { 181 return null; 182 } 183 184 @Override 185 public String version() { 186 // TODO: Make this more eloquent 187 return "0.3-alpha-DP"; 188 } 189 190 @Override 191 public PingInfo info() { 192 return pingInfo; 193 } 194 195 @Override 196 public TridentLogger logger() { 197 return logger; 198 } 199}