package com.planet_ink.coffee_mud.core.intermud.server;
import com.planet_ink.coffee_mud.core.intermud.imc2.*;
import com.planet_ink.coffee_mud.core.intermud.packets.*;
import com.planet_ink.coffee_mud.core.intermud.persist.*;
import com.planet_ink.coffee_mud.core.intermud.server.*;
import com.planet_ink.coffee_mud.core.intermud.net.*;
import com.planet_ink.coffee_mud.core.intermud.*;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;
/**
* com.planet_ink.coffee_mud.core.intermud.server.ServerThread
* Copyright (c) 1996 George Reese
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 1996 George Reese
* The actual thread that runs the mud.
*/
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* The Server class uses exactly one thread ServerThread object
* during the course of program execution. This thread loops
* until the Server class tells it to shut down. The loop is
* executed in the thread's run() method.
* @author George Reese (borg@imaginary.com)
* @version 1.0
* @see com.planet_ink.coffee_mud.core.intermud.server.Server
*/
public class ServerThread extends Thread {
private java.util.Date boot_time=null;
private int count = 1;
private Hashtable interactives;
private String mud_name;
private Hashtable objects;
private int port;
private boolean running;
private ImudServices intermuds;
private ListenThread listen_thread=null;
protected ServerThread(String mname,
int mport,
ImudServices imud) {
super("ServerThread");
setName("ServerThread");
setPriority(Thread.NORM_PRIORITY + 1);
setDaemon(true);
mud_name = mname;
port = mport;
intermuds=imud;
}
protected synchronized ServerObject copyObject(String str) throws ObjectLoadException {
ServerObject ob;
try {
ob = (ServerObject)Class.forName(str).newInstance();
count++;
str = str + "#" + count;
ob.setObjectId(str);
objects.put(str, ob);
}
catch( Exception e ) {
throw new ObjectLoadException("Failed to load object: " + e.getMessage());
}
return ob;
}
protected synchronized ServerObject findObject(String str) throws ObjectLoadException {
ServerObject ob;
if( objects.containsKey(str) ) {
ob = (ServerObject)objects.get(str);
if( ob.getDestructed() ) {
ob = null;
}
}
else {
ob = null;
}
if( ob == null ) {
try {
ob = (ServerObject)Class.forName(str).newInstance();
ob.setObjectId(str);
objects.put(str, ob);
}
catch( Exception e ) {
throw new ObjectLoadException("Failed to load object: " + e.getMessage());
}
}
return ob;
}
protected synchronized void removeObject(ServerObject ob) {
String id = ob.getObjectId();
if( !objects.containsKey(id) ) {
return;
}
objects.remove(id);
if( interactives.containsKey(id) ) {
interactives.remove(id);
}
}
/**
* While the mud is running, this method repeats the following
* steps over and over:
* <ul>
* <LI> Check for pending user input and trigger user commands
* <LI> Check for pending object events and execute them
* <LI> Check for incoming user connections and create an
* interactive object for each.
* </ul>
*/
public void run()
{
if( boot_time != null ) {
Log.errOut("I3Server","Illegal attempt to invoke run().");
return;
}
try {
listen_thread = new ListenThread(port);
}
catch( java.io.IOException e ) {
Log.errOut("I3Server",e.getMessage());
return;
}
try {
Intermud.setup(intermuds,
(PersistentPeer)Class.forName("com.planet_ink.coffee_mud.core.intermud.IMudPeer").newInstance());
}
catch( Exception e ) {
Log.errOut("I3Server",e.getMessage());
return;
}
boot_time = new java.util.Date();
Log.sysOut("I3Server", "InterMud3 Server started on port "+port);
synchronized( this )
{
objects = new Hashtable(1000, 100);
interactives = new Hashtable(50, 20);
}
running = true;
while( running ) {
ServerObject[] things;
ServerUser[] users;
try{
Thread.sleep(100);
}catch(Exception e){running=false;}
synchronized( this ) {
things = getObjects();
users = getInteractives();
}
{// Process all input
int i;
for(i=0; i<users.length; i++) {
ServerUser interactive = users[i];
if( interactive.getDestructed() ) {
continue;
}
try {
interactive.processInput();
}
catch( Exception e ) {
Log.errOut("IMServerThread",e);
}
}
}
{// Check for pending object events
int i;
for(i=0; i<things.length; i++) {
ServerObject thing = things[i];
if( !thing.getDestructed() ) {
try {
thing.processEvent();
}
catch( Exception e ) {
Log.errOut("IMServerThread",e);
}
}
}
}
{// Get new connections
int i;
for(i=0; i<5; i++) {
java.net.Socket s;
ServerUser new_user;
if(listen_thread!=null)
s = listen_thread.nextSocket();
else
s=null;
if( s == null ) {
break;
}
try {
new_user = (ServerUser)copyObject("com.planet_ink.coffee_mud.core.intermud.IMudUser");
}
catch( ObjectLoadException e ) {
continue;
}
try {
new_user.setSocket(s);
synchronized( this ) {
interactives.put(new_user.getObjectId(), new_user);
new_user.connect();
}
}
catch( java.io.IOException e ) {
new_user.destruct();
}
}
}
}
}
protected Date getBootTime() {
return boot_time;
}
protected synchronized ServerUser[] getInteractives() {
ServerUser[] tmp = new ServerUser[interactives.size()];
Enumeration e = interactives.elements();
int i = 0;
while( e.hasMoreElements() ) {
tmp[i++] = (ServerUser)e.nextElement();
}
return tmp;
}
protected String getMudName() {
return mud_name;
}
protected int getPort() {
return port;
}
public void shutdown()
{
running=false;
Intermud.shutdown();
if(listen_thread!=null)
{
listen_thread.close();
CMLib.killThread(listen_thread,500,1);
listen_thread=null;
}
boot_time = null;
try{ Thread.sleep(100);}catch(Exception e){}
}
protected synchronized ServerObject[] getObjects() {
ServerObject[] tmp = new ServerObject[objects.size()];
Enumeration e = objects.elements();
int i = 0;
while( e.hasMoreElements() ) {
tmp[i++] = (ServerObject)e.nextElement();
}
return tmp;
}
}