2010-12-22 16:22:23 +01:00
package net.minecraft.server ;
2011-01-29 22:50:29 +01:00
import java.awt.GraphicsEnvironment ;
2010-12-22 16:22:23 +01:00
import java.io.File ;
2011-01-11 09:25:13 +01:00
import java.io.IOException ;
2010-12-22 16:22:23 +01:00
import java.net.InetAddress ;
import java.util.ArrayList ;
import java.util.Collections ;
import java.util.HashMap ;
2010-12-28 20:52:24 +01:00
import java.util.Iterator ;
2010-12-22 16:22:23 +01:00
import java.util.List ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
2010-12-28 20:52:24 +01:00
2011-01-11 09:25:13 +01:00
// CraftBukkit start
2011-02-23 13:56:36 +01:00
import java.io.PrintStream ;
2011-01-11 09:25:13 +01:00
import java.net.UnknownHostException ;
2011-02-25 17:12:38 +01:00
import jline.ConsoleReader ;
2011-01-11 09:25:13 +01:00
import joptsimple.OptionSet ;
2011-02-01 19:13:12 +01:00
import org.bukkit.command.ConsoleCommandSender ;
2010-12-22 16:22:23 +01:00
import org.bukkit.craftbukkit.CraftServer ;
2011-02-20 02:53:06 +01:00
import org.bukkit.craftbukkit.LoggerOutputStream ;
2011-02-25 17:12:38 +01:00
import org.bukkit.craftbukkit.command.ColouredConsoleSender ;
2011-02-03 00:53:04 +01:00
import org.bukkit.craftbukkit.scheduler.CraftScheduler ;
2011-02-09 13:59:00 +01:00
import org.bukkit.event.Event ;
import org.bukkit.event.world.WorldEvent ;
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2010-12-22 16:22:23 +01:00
2011-02-23 03:37:56 +01:00
public class MinecraftServer implements Runnable , ICommandListener {
2010-12-22 16:22:23 +01:00
public static Logger a = Logger . getLogger ( " Minecraft " ) ;
2011-01-11 09:25:13 +01:00
public static HashMap b = new HashMap ( ) ;
2010-12-26 03:20:29 +01:00
public NetworkListenThread c ;
public PropertyManager d ;
2011-02-23 13:56:36 +01:00
// public WorldServer e; // CraftBukkit - removed
2010-12-26 03:20:29 +01:00
public ServerConfigurationManager f ;
2011-02-23 03:37:56 +01:00
private ConsoleCommandHandler o ;
private boolean p = true ;
2011-01-29 22:50:29 +01:00
public boolean g = false ;
int h = 0 ;
2010-12-22 16:22:23 +01:00
public String i ;
public int j ;
2011-02-23 03:37:56 +01:00
private List q = new ArrayList ( ) ;
private List r = Collections . synchronizedList ( new ArrayList ( ) ) ;
2010-12-26 03:20:29 +01:00
public EntityTracker k ;
2010-12-22 16:22:23 +01:00
public boolean l ;
public boolean m ;
public boolean n ;
2010-12-28 20:52:24 +01:00
2011-02-23 13:56:36 +01:00
// CraftBukkit start
2011-02-21 23:30:01 +01:00
public int spawnProtection ;
public List < WorldServer > worlds = new ArrayList < WorldServer > ( ) ;
2011-01-29 22:50:29 +01:00
public CraftServer server ;
public OptionSet options ;
2011-02-25 17:12:38 +01:00
public ColouredConsoleSender console ;
public ConsoleReader reader ;
2011-02-21 23:30:01 +01:00
// Craftbukkit end
2010-12-22 16:22:23 +01:00
2011-02-23 13:56:36 +01:00
public MinecraftServer ( OptionSet options ) { // CraftBukkit - adds argument OptionSet
2011-02-21 23:30:01 +01:00
new ThreadSleepForever ( this ) ;
2011-02-25 17:12:38 +01:00
// CraftBukkit start
this . options = options ;
try {
this . reader = new ConsoleReader ( ) ;
} catch ( IOException ex ) {
Logger . getLogger ( MinecraftServer . class . getName ( ) ) . log ( Level . SEVERE , null , ex ) ;
}
// CraftBukkit end
2011-02-21 23:30:01 +01:00
}
private boolean d ( ) throws UnknownHostException { // CraftBukkit - added throws UnknownHostException
2011-02-23 03:37:56 +01:00
this . o = new ConsoleCommandHandler ( this ) ;
2010-12-28 20:52:24 +01:00
ThreadCommandReader threadcommandreader = new ThreadCommandReader ( this ) ;
2010-12-22 16:22:23 +01:00
2011-01-29 22:50:29 +01:00
threadcommandreader . setDaemon ( true ) ;
threadcommandreader . start ( ) ;
2011-02-25 17:12:38 +01:00
ConsoleLogManager . a ( reader ) ; // Craftbukkit
2011-02-20 02:53:06 +01:00
2011-02-23 13:56:36 +01:00
// CraftBukkit start
2011-02-20 02:53:06 +01:00
System . setOut ( new PrintStream ( new LoggerOutputStream ( a , Level . INFO ) , true ) ) ;
System . setErr ( new PrintStream ( new LoggerOutputStream ( a , Level . SEVERE ) , true ) ) ;
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2011-02-20 02:53:06 +01:00
2011-02-23 03:37:56 +01:00
a . info ( " Starting minecraft server version Beta 1.3 " ) ;
2010-12-22 16:22:23 +01:00
if ( Runtime . getRuntime ( ) . maxMemory ( ) / 1024L / 1024L < 512L ) {
a . warning ( " **** NOT ENOUGH RAM! " ) ;
a . warning ( " To start the server with more ram, launch it as \" java -Xmx1024M -Xms1024M -jar minecraft_server.jar \" " ) ;
}
2011-01-29 22:50:29 +01:00
2010-12-22 16:22:23 +01:00
a . info ( " Loading properties " ) ;
2011-02-23 13:56:36 +01:00
this . d = new PropertyManager ( options ) ; // CraftBukkit
2011-01-29 22:50:29 +01:00
String s = this . d . a ( " server-ip " , " " ) ;
2010-12-22 16:22:23 +01:00
2011-01-29 22:50:29 +01:00
this . l = this . d . a ( " online-mode " , true ) ;
this . m = this . d . a ( " spawn-animals " , true ) ;
this . n = this . d . a ( " pvp " , true ) ;
2011-02-10 05:02:37 +01:00
this . spawnProtection = this . d . a ( " spawn-protection " , 16 ) ; // CraftBukkit Configurable spawn protection start
2010-12-28 20:52:24 +01:00
InetAddress inetaddress = null ;
2010-12-22 16:22:23 +01:00
2010-12-28 20:52:24 +01:00
if ( s . length ( ) > 0 ) {
inetaddress = InetAddress . getByName ( s ) ;
2010-12-22 16:22:23 +01:00
}
2011-01-29 22:50:29 +01:00
int i = this . d . a ( " server-port " , 25565 ) ;
a . info ( " Starting Minecraft server on " + ( s . length ( ) = = 0 ? " * " : s ) + " : " + i ) ;
2010-12-22 16:22:23 +01:00
try {
2011-01-29 22:50:29 +01:00
this . c = new NetworkListenThread ( this , inetaddress , i ) ;
2011-02-21 23:30:01 +01:00
} catch ( Throwable ioexception ) { // CraftBukkit - IOException -> Throwable
2010-12-22 16:22:23 +01:00
a . warning ( " **** FAILED TO BIND TO PORT! " ) ;
2011-01-29 22:50:29 +01:00
a . log ( Level . WARNING , " The exception was: " + ioexception . toString ( ) ) ;
2010-12-22 16:22:23 +01:00
a . warning ( " Perhaps a server is already running on that port? " ) ;
return false ;
}
2011-01-29 22:50:29 +01:00
if ( ! this . l ) {
2010-12-22 16:22:23 +01:00
a . warning ( " **** SERVER IS RUNNING IN OFFLINE/INSECURE MODE! " ) ;
a . warning ( " The server will make no attempt to authenticate usernames. Beware. " ) ;
a . warning ( " While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose. " ) ;
a . warning ( " To change this, set \" online-mode \" to \" true \" in the server.settings file. " ) ;
}
2010-12-26 03:20:29 +01:00
2011-01-29 22:50:29 +01:00
this . f = new ServerConfigurationManager ( this ) ;
this . k = new EntityTracker ( this ) ;
2011-02-23 03:37:56 +01:00
long j = System . nanoTime ( ) ;
2011-01-29 22:50:29 +01:00
String s1 = this . d . a ( " level-name " , " world " ) ;
a . info ( " Preparing level \" " + s1 + " \" " ) ;
2011-02-23 03:37:56 +01:00
this . a ( ( Convertable ) ( new WorldLoaderServer ( new File ( " . " ) ) ) , s1 ) ;
2011-02-25 21:57:38 +01:00
// CraftBukkit start
long elapsed = System . nanoTime ( ) - j ;
String time = String . format ( " %.3fs " , elapsed / 10000000000 . 0D ) ;
a . info ( " Done ( " + time + " )! For help, type \" help \" or \" ? \" " ) ;
// CraftBukkit end
2010-12-22 16:22:23 +01:00
return true ;
}
2011-02-23 03:37:56 +01:00
private void a ( Convertable convertable , String s ) {
if ( convertable . a ( s ) ) {
a . info ( " Converting map! " ) ;
convertable . a ( s , new ConvertProgressUpdater ( this ) ) ;
}
2010-12-22 16:22:23 +01:00
a . info ( " Preparing start region " ) ;
2011-02-05 19:15:04 +01:00
2011-02-23 13:56:36 +01:00
// CraftBukkit start
2011-02-23 03:37:56 +01:00
WorldServer world = new WorldServer ( this , new ServerNBTManager ( new File ( " . " ) , s , true ) , s , this . d . a ( " hellworld " , false ) ? - 1 : 0 ) ;
2011-02-05 19:15:04 +01:00
world . a ( new WorldManager ( this , world ) ) ;
2011-02-23 03:37:56 +01:00
world . j = this . d . a ( " spawn-monsters " , true ) ? 1 : 0 ;
2011-02-05 19:15:04 +01:00
world . a ( this . d . a ( " spawn-monsters " , true ) , this . m ) ;
this . f . a ( world ) ;
worlds . add ( world ) ;
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2011-02-05 19:15:04 +01:00
2011-01-29 22:50:29 +01:00
short short1 = 196 ;
long i = System . currentTimeMillis ( ) ;
2011-02-23 13:56:36 +01:00
ChunkCoordinates chunkcoordinates = worlds . get ( 0 ) . l ( ) ; // CraftBukkit
2011-01-29 22:50:29 +01:00
2011-02-23 03:37:56 +01:00
for ( int j = - short1 ; j < = short1 & & this . p ; j + = 16 ) {
for ( int k = - short1 ; k < = short1 & & this . p ; k + = 16 ) {
2011-01-29 22:50:29 +01:00
long l = System . currentTimeMillis ( ) ;
if ( l < i ) {
i = l ;
2011-01-14 14:31:10 +01:00
}
2011-01-29 22:50:29 +01:00
if ( l > i + 1000L ) {
int i1 = ( short1 * 2 + 1 ) * ( short1 * 2 + 1 ) ;
int j1 = ( j + short1 ) * ( short1 * 2 + 1 ) + k + 1 ;
this . a ( " Preparing spawn area " , j1 * 100 / i1 ) ;
i = l ;
2011-01-14 14:31:10 +01:00
}
2011-01-29 22:50:29 +01:00
2011-02-23 13:56:36 +01:00
// CraftBukkit start
for ( WorldServer worldserver : worlds ) {
2011-02-23 03:37:56 +01:00
world . u . d ( chunkcoordinates . a + j > > 4 , chunkcoordinates . c + k > > 4 ) ;
2011-01-29 22:50:29 +01:00
2011-02-23 03:37:56 +01:00
while ( world . e ( ) & & this . p ) {
2011-02-05 19:15:04 +01:00
;
}
2010-12-22 16:22:23 +01:00
}
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2010-12-22 16:22:23 +01:00
}
}
2010-12-28 20:52:24 +01:00
2011-01-29 22:50:29 +01:00
this . e ( ) ;
2010-12-22 16:22:23 +01:00
}
2011-01-29 22:50:29 +01:00
private void a ( String s , int i ) {
this . i = s ;
this . j = i ;
a . info ( s + " : " + i + " % " ) ;
2010-12-22 16:22:23 +01:00
}
private void e ( ) {
2011-01-29 22:50:29 +01:00
this . i = null ;
this . j = 0 ;
2011-01-11 09:25:13 +01:00
server . loadPlugins ( ) ; // CraftBukkit
2010-12-22 16:22:23 +01:00
}
2011-02-25 18:15:43 +01:00
void f ( ) { //CraftBukkit - private -> default
2010-12-22 16:22:23 +01:00
a . info ( " Saving chunks " ) ;
2011-02-05 19:15:04 +01:00
2011-02-23 13:56:36 +01:00
// CraftBukkit start
for ( WorldServer world : worlds ) {
2011-02-05 19:15:04 +01:00
world . a ( true , ( IProgressUpdate ) null ) ;
2011-02-23 03:37:56 +01:00
world . r ( ) ;
2011-02-19 21:29:51 +01:00
2011-02-23 13:56:36 +01:00
WorldEvent event = new WorldEvent ( Event . Type . WORLD_SAVED , world . getWorld ( ) ) ;
server . getPluginManager ( ) . callEvent ( event ) ;
2011-02-05 19:15:04 +01:00
}
2011-02-25 18:15:43 +01:00
this . f . d ( ) ; // CraftBukkit - player data should be saved whenever a save happens.
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2010-12-22 16:22:23 +01:00
}
private void g ( ) {
a . info ( " Stopping server " ) ;
2011-02-21 23:30:01 +01:00
// CraftBukkit start
2011-02-23 13:56:36 +01:00
if ( server ! = null ) {
2011-02-01 21:37:07 +01:00
server . disablePlugins ( ) ;
}
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2011-02-02 00:32:18 +01:00
2011-01-29 22:50:29 +01:00
if ( this . f ! = null ) {
this . f . d ( ) ;
2011-01-27 22:15:41 +01:00
}
2011-02-23 13:56:36 +01:00
if ( this . worlds . size ( ) > 0 ) { // CraftBukkit
2011-01-29 22:50:29 +01:00
this . f ( ) ;
2010-12-22 16:22:23 +01:00
}
}
public void a ( ) {
2011-02-23 03:37:56 +01:00
this . p = false ;
2010-12-22 16:22:23 +01:00
}
public void run ( ) {
try {
2011-01-29 22:50:29 +01:00
if ( this . d ( ) ) {
long i = System . currentTimeMillis ( ) ;
2010-12-28 20:52:24 +01:00
2011-02-23 03:37:56 +01:00
for ( long j = 0L ; this . p ; Thread . sleep ( 1L ) ) {
2011-01-29 22:50:29 +01:00
long k = System . currentTimeMillis ( ) ;
long l = k - i ;
2010-12-28 20:52:24 +01:00
2011-01-29 22:50:29 +01:00
if ( l > 2000L ) {
a . warning ( " Can \ 't keep up! Did the system time change, or is the server overloaded? " ) ;
l = 2000L ;
2010-12-22 16:22:23 +01:00
}
2011-01-29 22:50:29 +01:00
if ( l < 0L ) {
2010-12-22 16:22:23 +01:00
a . warning ( " Time ran backwards! Did the system time change? " ) ;
2011-01-29 22:50:29 +01:00
l = 0L ;
2010-12-22 16:22:23 +01:00
}
2011-01-29 22:50:29 +01:00
j + = l ;
i = k ;
2011-02-23 13:56:36 +01:00
// CraftBukkit - TODO - Replace with loop?
if ( this . worlds . size ( ) > 0 & & this . worlds . get ( 0 ) . q ( ) ) {
2011-01-29 22:50:29 +01:00
this . h ( ) ;
2011-02-23 03:37:56 +01:00
j = 0L ;
} else {
while ( j > 50L ) {
j - = 50L ;
this . h ( ) ;
}
2010-12-22 16:22:23 +01:00
}
}
} else {
2011-02-23 03:37:56 +01:00
while ( this . p ) {
2011-01-29 22:50:29 +01:00
this . b ( ) ;
2010-12-22 16:22:23 +01:00
try {
Thread . sleep ( 10L ) ;
2010-12-28 20:52:24 +01:00
} catch ( InterruptedException interruptedexception ) {
interruptedexception . printStackTrace ( ) ;
2010-12-22 16:22:23 +01:00
}
}
}
2011-02-23 03:37:56 +01:00
} catch ( Throwable throwable ) {
throwable . printStackTrace ( ) ;
a . log ( Level . SEVERE , " Unexpected exception " , throwable ) ;
2011-01-29 22:50:29 +01:00
2011-02-23 03:37:56 +01:00
while ( this . p ) {
2011-01-29 22:50:29 +01:00
this . b ( ) ;
2010-12-22 16:22:23 +01:00
try {
Thread . sleep ( 10L ) ;
2010-12-28 20:52:24 +01:00
} catch ( InterruptedException interruptedexception1 ) {
interruptedexception1 . printStackTrace ( ) ;
2010-12-22 16:22:23 +01:00
}
}
} finally {
2011-01-14 14:31:10 +01:00
try {
2011-01-29 22:50:29 +01:00
this . g ( ) ;
this . g = true ;
2011-02-23 03:37:56 +01:00
} catch ( Throwable throwable1 ) {
throwable1 . printStackTrace ( ) ;
2011-01-14 14:31:10 +01:00
} finally {
System . exit ( 0 ) ;
}
2010-12-22 16:22:23 +01:00
}
}
private void h ( ) {
2011-01-11 09:25:13 +01:00
ArrayList arraylist = new ArrayList ( ) ;
2011-01-29 22:50:29 +01:00
Iterator iterator = b . keySet ( ) . iterator ( ) ;
2010-12-28 20:52:24 +01:00
2011-01-29 22:50:29 +01:00
while ( iterator . hasNext ( ) ) {
2010-12-28 20:52:24 +01:00
String s = ( String ) iterator . next ( ) ;
2011-01-29 22:50:29 +01:00
int i = ( ( Integer ) b . get ( s ) ) . intValue ( ) ;
2010-12-28 20:52:24 +01:00
2011-01-29 22:50:29 +01:00
if ( i > 0 ) {
b . put ( s , Integer . valueOf ( i - 1 ) ) ;
2010-12-22 16:22:23 +01:00
} else {
2011-01-29 22:50:29 +01:00
arraylist . add ( s ) ;
2010-12-22 16:22:23 +01:00
}
}
2010-12-28 20:52:24 +01:00
2011-01-29 22:50:29 +01:00
int j ;
for ( j = 0 ; j < arraylist . size ( ) ; + + j ) {
b . remove ( arraylist . get ( j ) ) ;
2010-12-22 16:22:23 +01:00
}
2010-12-26 03:20:29 +01:00
AxisAlignedBB . a ( ) ;
Vec3D . a ( ) ;
2011-01-29 22:50:29 +01:00
+ + this . h ;
2011-02-05 19:15:04 +01:00
2011-02-23 13:56:36 +01:00
// CraftBukkit start
2011-01-29 22:50:29 +01:00
if ( this . h % 20 = = 0 ) {
2011-02-05 19:15:04 +01:00
for ( int i = 0 ; i < this . f . b . size ( ) ; + + i ) {
EntityPlayer entityplayer = ( EntityPlayer ) this . f . b . get ( i ) ;
2011-02-23 03:37:56 +01:00
entityplayer . a . b ( ( Packet ) ( new Packet4UpdateTime ( entityplayer . world . k ( ) ) ) ) ;
2011-02-05 19:15:04 +01:00
}
2010-12-22 16:22:23 +01:00
}
2011-02-07 02:59:06 +01:00
( ( CraftScheduler ) server . getScheduler ( ) ) . mainThreadHeartbeat ( this . h ) ;
2011-02-19 21:29:51 +01:00
2011-02-23 13:56:36 +01:00
for ( WorldServer world : worlds ) {
2011-02-23 03:37:56 +01:00
world . g ( ) ;
2011-01-29 22:50:29 +01:00
2011-02-23 03:37:56 +01:00
while ( world . e ( ) ) {
2011-02-05 19:15:04 +01:00
;
}
2011-02-19 21:29:51 +01:00
2011-02-23 03:37:56 +01:00
world . d ( ) ;
2010-12-22 16:22:23 +01:00
}
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2011-01-29 22:50:29 +01:00
this . c . a ( ) ;
this . f . b ( ) ;
this . k . a ( ) ;
2011-02-23 03:37:56 +01:00
for ( j = 0 ; j < this . q . size ( ) ; + + j ) {
( ( IUpdatePlayerListBox ) this . q . get ( j ) ) . a ( ) ;
2010-12-28 20:52:24 +01:00
}
2010-12-22 16:22:23 +01:00
try {
2011-01-29 22:50:29 +01:00
this . b ( ) ;
2010-12-28 20:52:24 +01:00
} catch ( Exception exception ) {
2011-01-29 22:50:29 +01:00
a . log ( Level . WARNING , " Unexpected exception while parsing console command " , exception ) ;
2010-12-22 16:22:23 +01:00
}
}
2010-12-28 20:52:24 +01:00
public void a ( String s , ICommandListener icommandlistener ) {
2011-02-23 03:37:56 +01:00
this . r . add ( new ServerCommand ( s , icommandlistener ) ) ;
2010-12-22 16:22:23 +01:00
}
public void b ( ) {
2011-02-23 03:37:56 +01:00
while ( this . r . size ( ) > 0 ) {
ServerCommand servercommand = ( ServerCommand ) this . r . remove ( 0 ) ;
2010-12-28 20:52:24 +01:00
2011-02-23 13:56:36 +01:00
// CraftBukkit start
2011-02-23 03:37:56 +01:00
if ( server . dispatchCommand ( console , servercommand . a ) ) {
2011-02-01 19:13:12 +01:00
continue ;
}
2011-02-23 13:56:36 +01:00
// CraftBukkit end
2011-02-23 03:37:56 +01:00
this . o . a ( servercommand ) ;
2010-12-22 16:22:23 +01:00
}
}
2010-12-28 20:52:24 +01:00
public void a ( IUpdatePlayerListBox iupdateplayerlistbox ) {
2011-02-23 03:37:56 +01:00
this . q . add ( iupdateplayerlistbox ) ;
2010-12-22 16:22:23 +01:00
}
2011-02-23 13:56:36 +01:00
public static void main ( final OptionSet options ) { // CraftBukkit - replaces main(String args[])
2010-12-22 16:22:23 +01:00
try {
2011-01-30 13:51:20 +01:00
MinecraftServer minecraftserver = new MinecraftServer ( options ) ;
2011-01-29 22:50:29 +01:00
2011-01-11 09:25:13 +01:00
// CraftBukkit - remove gui
2010-12-22 16:22:23 +01:00
2010-12-28 20:52:24 +01:00
( new ThreadServerApplication ( " Server thread " , minecraftserver ) ) . start ( ) ;
} catch ( Exception exception ) {
2011-01-29 22:50:29 +01:00
a . log ( Level . SEVERE , " Failed to start the minecraft server " , exception ) ;
2010-12-22 16:22:23 +01:00
}
}
2010-12-28 20:52:24 +01:00
public File a ( String s ) {
return new File ( s ) ;
2010-12-22 16:22:23 +01:00
}
2010-12-28 20:52:24 +01:00
public void b ( String s ) {
a . info ( s ) ;
2010-12-22 16:22:23 +01:00
}
public String c ( ) {
return " CONSOLE " ;
}
2010-12-28 20:52:24 +01:00
public static boolean a ( MinecraftServer minecraftserver ) {
2011-02-23 03:37:56 +01:00
return minecraftserver . p ;
2010-12-28 20:52:24 +01:00
}
2011-01-11 09:25:13 +01:00
}