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; } }