From: Snowdog <sn...@ga...> - 2013-11-15 17:34:08
|
Very little would actually need to be changed. Simply need to create a new GUI Manager that does nothing with the JPanels it’s handed and toggle what GUI Manager gets used based on command line args. Ideally the server side modules should be able to detect the ‘headless’ run state and never create their GUI components to minimize resource usage. Currently this is at the bottom of a long list of ‘to-dos’. The original design was to have the server be headless and connect to it with a dedicated GUI server-controller client. This is possible because the module initialization occurs post connection and the server doesn’t care what modules a client actually has. e.g. the server can play nice with multiple types of clients at the same time. Also would potentially allow servers to connect to and talk to other servers as peers. The existing server GUI was born to facilitate early testing. Though I’m sure some people (*cough* Windows users *cough*) will probably prefer the server having a built-in GUI. Running a GUI server is not going to be required for sure. —Snowdog On Nov 14, 2013, at 5:47 PM, Mark Tarrabain <ma...@ly...> wrote: > Thanks, > > One more thing, also... > > I notice that the server has a GUI.... how major of a change would it > be to make the server work in a headless environment. While many people > may be satisfied with it taking up a window, I would expect that not > everyone would be. Such a headless server need only log text output > normally, and should not have a gui. Ideally, we could use a separate > program which talks to the server on a localhost, and which may act as a > gui environment for people who want to have a user interface over a > server that has no UI. > > Mark > > > On 11/14/2013 04:17 PM, Snowdog wrote: >> I’ll tackle these inline… so see below. >> >> On Nov 14, 2013, at 1:54 PM, Mark Tarrabain <ma...@ly...> wrote: >> >>> Hey, >>> >>> Well, a recent and rather unexpected change in my employment status has >>> opened up my schedule a whole lot, and since I've really wanted to do >>> some work on this, I might as well take advantage of the time I have >>> right now to do so. >> >> Ironically the exact opposite has happened to me. I’m starting a new job and loosing lots of time. :-/ >> >>> So... first things first. >>> >>> It seems there is some sort of logical error in the client-server >>> connectivity, since I cannot seem to disconnect from a server that I've >>> connected to. >> >> The client side network module is new, and admittedly lacks some polish to put _very_ kindly. ;-) >> Yes, there indeed is a disconnection issue. The client/server do indeed disconnect, >> but they do so on their own whims (or so it seems). Its a thread based timing thing i believe. >> The async nature of the network code poses some _significant_ challenges to what >> would be otherwise simple setup/teardown of the network pipe. We have to arbitrarily wait >> while other modules do their syncing before actually shutting down the pipe. >> >> I’ll be the first to admit, sometimes I think I’ve dug myself into a huge hole with this design, >> but other times things slips together so simply and easily I know its going to work great >> down the road. All the hard stuff is up front, once thats handled module writers should >> have a simple time of adding to this design. Till then though… expect to loose hair lol. >> >> >>> Also, it's been a while since I looked at the code here and I'm not sure >>> I'm getting my brain wrapped around how the whole system is structured. >> >> Yeah, the base structure is…. different. Because of the multi-threaded modular nature of the core >> it makes visualizing how things work difficult. I’ll try to boil it down for you. Remember this is all OOD/P so there is little in the way of a ‘flow’ to follow. >> I’ll reference key classes as I go... >> >> Basically, we have 3 subsystems (Layers) that each run in its own thread by the “Engine” (common.core.engine.Engine) >> 1) Network Layer (common.core.network.NetworkServer & common.core.network.NetworkClient) >> The network manages all connections and network I/O using a pool of worker threads >> The network sends/receives ORPGMessages (common.core.ORPGMessage) to/from the Module Layer >> 2) Module Layer >> All features of the system are ‘Modules’, i.e. ‘chat module’, ‘whiteboard module’, etc. >> All modules register with the ModuleManager (common.core.engine.ModuleManager) via the module loader (server.core.ServerModuleLoader & client.core.ClientModuleLoader) >> They register what types of messages they receive & send, register interest in other modules, register gui components, etc with the Module Manager. >> This is a key point…. Modules CANNOT interact directly with other modules, they MUST go through the ModuleManager. >> 3) GUI Layer (common.core.gui.GUIManager) >> All GUI components for registered modules and handled as JPanels by a GUIManager. >> Each panel is controlled and managed by its respective owning module. >> >>> Snowdog, could you please walk me through how the module system works, >>> exactly? What does a client and server have to do to register a >>> module? >> >> Eventually we will be able to dynamically load modules, but currently only ‘core’ static >> modules are loaded via the respective module loader (server.core.ServerModuleLoader & client.core.ClientModuleLoader) >> >> The module loader then instances the module and calls its doRegistration() method (see bottom of ExampleClientModule.java). >> The module class handles it’s own registering with the ModuleManager. >> >>> How does a client module send or receive data from the server, >>> and how does a module on the server send or receive data from clients? >> >> Check out the Example modules (client.core.modules.ExampleClientModule ) >> Messages between the client/server or client/client(s) is accomplished using a simple header/data structure (based on a TCP/IP packet design) >> 1) Create an ORPGMessage >> 2) Set the message type so the receiver(s) know what module this is destined for >> 3) Set any header data [optional, but useful for small messages] >> 4) Set data payload [optional] >> 5) Create a MessageAddress (contains details for delivery of message) and set the destination for the ORPGMessage >> 6) Push the ORPGMessage to the ModuleManager via sendToNetwork() call. >> >> Note: The data payload will be sent as binary so the structure of the data is up to individual modules. >> Could be text, XML, binary, JSON, etc. As the data portion of the message will only be parsed by the >> receiving module (and then only if needed presumably) it greatly cuts down on message parsing times >> (as only header is parsed) >> >>> I am thinking of working on the chat/channel system, if you haven't >>> already started on that. >> >> I have not started on either as all of my work has been much lower level. >> >>> Once that's complete, I will work on a channel-based whiteboard that can >>> be viewed by all within the channel, which will ultimately function as >>> the channel's map. >>> >>> Mark >> >> It should be noted that the server does not need to have a module for a given module. >> As it only parses the message header (for addressing info) it does not NEED to handle the message, >> only route it to the correct client. This means that technically, you only need a client side module for most tasks. >> >> The server contains a special ‘fallback’ module called ‘DefaultRelay’ that accepts all unknown messages and simply forwards them based on their MessageAddress data. >> >> let me know if you need any more info. >> >> >> --Snowdog >> >> >> |