work on the client side...

gh-pages
Brian Jack 2014-12-11 12:50:43 -08:00
parent 9c044e8971
commit 619bd1222b
4 changed files with 133 additions and 115 deletions

View File

@ -20,3 +20,10 @@
/** @brief meters per parsec */
u64 m_per_parsec=30856775800000000;
int widen(std::wstring &wide,const std::string &narrow) {
std::wstring ws(narrow.size(), L' '); // Overestimate number of code points.
ws.resize(mbstowcs(&ws[0], narrow.c_str(), narrow.size())); // Shrink to fit.
wide=ws;
return 0;
}

View File

@ -85,4 +85,6 @@ public:
virtual void accept(IVisitor &v) {v.visit(this);}
};
extern int widen(std::wstring &,const std::string &);
#endif // BV_COMMON_HPP_INCLUDED

View File

@ -10,10 +10,14 @@ opcode overview:
objectref: o id
method call: . id method
object gone: ~ id
dmc message: : id len name midx
atomic: ( <params> <method call> )
```
- db is a raw databyte
- len is a LE 32-bit unsigned integer
- id is LE 32-bit unsigned integer object id
- midx is LE 32-bit unsigned integer method index
- name is a string (preceeding len is length)
- method is LE 32-bit unsigned integer method index
debug mode:
@ -22,6 +26,41 @@ will be indicated as hexadecimal representations matching the
length of data involved
0xNNNNNNNN for #, 0xNN for databytes
atomic blocks:
If the endpoints were to invoke a method call with arguments then
concurrnecy issues may occur as parameters of endpoint B's method
call get interpreted by enpoint A as return values to its current
method call (or vice versa). To prevent such problems one endpoint
(the server by convention since its calls tend to be preemptive in
nature) brackets its calls with the atomic operators ( and ) which
tells the receiver not to use the normal argument stack to hold the
bracketed values. This stack is destroyed when the closing ) is
encountered. Atomic blocks are meant to make preemptive (out of
band) informational calls to 'sink' type methods that may accept
arguments but may not push return values.
NB: Method calls that neither accept parameters nor generate
return values do not need to use atomic blocks.
*** TODO ***
The current protocol implementation does not yet implement
atomic blocks.
dynamic method call (DMC):
Objects may be polymorphic (as a derived class during program
compilation) and may also add additional methods at runtime.
Whenever the object first becomes valid at one endpoint an
initial set of dmc messages will convey the initial interface
to the other endpoint.
If the object instance polymorphs further at runtime then
additional dmc messages may be emitted whenever such changes
occur. Instances may only add new methods to the existing
contract, never remove an existing method.
##datatypes
decimals: f [-] [ &lt;whole digits&gt; ] [ . &lt;fraction digits&gt; ] [ e &lt;exponent digits&gt; ] ;

View File

@ -38,26 +38,7 @@
#include "client.hpp"
#include "settings.hpp"
/*
In the Irrlicht Engine, everything can be found in the namespace
'irr'. So if you want to use a class of the engine, you have to
write an irr:: before the name of the class. For example to use
the IrrlichtDevice write: irr::IrrlichtDevice. To get rid of the
irr:: in front of the name of every class, we tell the compiler
that we use that namespace from now on, and we will not have to
write that 'irr::'.
*/
using namespace irr;
/*
There are 5 sub namespaces in the Irrlicht Engine. Take a look
at them, you can read a detailed description of them in the
documentation by clicking on the top menu item 'Namespace List'
or using this link: http://irrlicht.sourceforge.net/docu/namespaces.html.
Like the irr Namespace, we do not want these 5 sub namespaces now,
to keep this example simple. Hence we tell the compiler again
that we do not want always to write their names:
*/
using namespace core;
using namespace scene;
using namespace video;
@ -175,8 +156,11 @@ int main(int argc, char** argv)
Configurator config((cwd/"client.cfg").string(),client_default_config);
config.read_cmdline(argc,argv);
std::string ver=auto_ver;
std::wstring wcvt;
LOCK_COUT
cout << "Client version is: " << auto_ver << endl;
cout << "Client version is: " << ver << endl;
cout << "Client starting in: " << cwd << endl;
/* test settings map */
/*for (auto &setting : config) {
@ -185,6 +169,44 @@ int main(int argc, char** argv)
}*/
UNLOCK_COUT
E_DRIVER_TYPE vdrv=EDT_SOFTWARE;
if (v2str(config["driver"])=="opengl") vdrv=EDT_OPENGL;
int winW,winH;
winW=v2int(config["window_width"]);
winH=v2int(config["window_height"]);
IrrlichtDevice *device =
createDevice(vdrv, dimension2d<u32>(winW, winH), 16,
false, false, false, 0);
device->setWindowCaption(L"Blockiverse client");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
guienv->clear();
widen(wcvt,std::string("Blockiverse version ")+ver+" starting up...");
guienv->addStaticText(wcvt.data(),
rect<int>(10,10,200,22), false);
if (!device->run()) {return 0;}
driver->beginScene(true, true, SColor(0,200,200,200));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
/*
** start server when running standalone
** so there will be something to connect to
*/
bool standalone=(0!=v2int(config["standalone"]));
if (standalone) {
LOCK_COUT
cout << "Starting server." << endl;
UNLOCK_COUT
serverActive=true;
req_serverQuit=false;
server_thread=new boost::thread(server_main,&args);
}
/*
** load client keypair
** or generate if they do not exist
@ -214,9 +236,23 @@ int main(int argc, char** argv)
UNLOCK_COUT
}
if (client_kpair==NULL) {
guienv->clear();
widen(wcvt,std::string(
"Generating new client key.\n"
" This is only done once after installation,\n"
" but may take a few minutes..."));
guienv->addStaticText(wcvt.data(),
rect<int>(10,10,200,10+(12*3)), false);
if (!device->run()) {return 0;}
driver->beginScene(true, true, SColor(0,200,200,200));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
LOCK_COUT
cout << "Generating new client key" << endl
<< " This is only done once," << endl
<< " This is only done once after installation," << endl
<< " but it takes several minutes..." << endl;
UNLOCK_COUT
/*
@ -254,19 +290,17 @@ int main(int argc, char** argv)
//cout << *client_kpair << endl;
//UNLOCK_COUT
/*
** start server when running standalone
** so there will be something to connect to
*/
bool standalone=(0!=v2int(config["standalone"]));
if (standalone) {
LOCK_COUT
cout << "Starting server." << endl;
UNLOCK_COUT
serverActive=true;
req_serverQuit=false;
server_thread=new boost::thread(server_main,&args);
}
guienv->clear();
widen(wcvt,std::string("Logging into ")
+config["address"]+":"+config["port"]
+" as "+config["user"]+"...");
guienv->addStaticText(wcvt.data(),
rect<int>(10,10,400,22), false);
if (!device->run()) {return 0;}
driver->beginScene(true, true, SColor(0,200,200,200));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
/*
** create stuff client needs such as
@ -356,54 +390,7 @@ int main(int argc, char** argv)
UNLOCK_COUT
if (acctId>0){
/*
The most important function of the engine is the 'createDevice'
function. The Irrlicht Device can be created with it, which is the
root object for doing everything with the engine.
createDevice() has 7 paramters:
deviceType: Type of the device. This can currently be the Null-device,
the Software device, DirectX8, DirectX9, or OpenGL. In this example we use
EDT_SOFTWARE, but to try out, you might want to change it to
EDT_NULL, EDT_DIRECTX8 , EDT_DIRECTX9, or EDT_OPENGL.
windowSize: Size of the Window or FullscreenMode to be created. In this
example we use 640x480.
bits: Amount of bits per pixel when in fullscreen mode. This should
be 16 or 32. This parameter is ignored when running in windowed mode.
fullscreen: Specifies if we want the device to run in fullscreen mode
or not.
stencilbuffer: Specifies if we want to use the stencil buffer for drawing shadows.
vsync: Specifies if we want to have vsync enabled, this is only useful in fullscreen
mode.
eventReceiver: An object to receive events. We do not want to use this
parameter here, and set it to 0.
*/
E_DRIVER_TYPE vdrv=EDT_SOFTWARE;
if (v2str(config["driver"])=="opengl") vdrv=EDT_OPENGL;
int winW,winH;
winW=v2int(config["window_width"]);
winH=v2int(config["window_height"]);
IrrlichtDevice *device =
createDevice(vdrv, dimension2d<u32>(winW, winH), 16,
false, false, false, 0);
/*
Set the caption of the window to some nice text. Note that there is
a 'L' in front of the std::string. The Irrlicht Engine uses wide character
std::strings when displaying text.
*/
device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
/*
Get a pointer to the video driver, the SceneManager and the
graphical user interface environment, so that
we do not always have to write device->getVideoDriver(),
device->getSceneManager() and device->getGUIEnvironment().
*/
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
guienv->clear();
/*
We add a hello world label to the window, using the GUI environment.
@ -498,31 +485,12 @@ int main(int argc, char** argv)
UNLOCK_COUT
}
/*
Anything can be drawn between a beginScene() and an endScene()
call. The beginScene clears the screen with a color and also the
depth buffer if wanted. Then we let the Scene Manager and the
GUI Environment draw their content. With the endScene() call
everything is presented on the screen.
*/
driver->beginScene(true, true, SColor(0,200,200,200));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
/*
After we are finished, we have to delete the Irrlicht Device
created before with createDevice(). In the Irrlicht Engine,
you will have to delete all objects you created with a method or
function which starts with 'create'. The object is simply deleted
by calling ->drop().
See the documentation at
http://irrlicht.sourceforge.net//docu/classirr_1_1IUnknown.html#a3
for more information.
*/
device->drop();
}
}
@ -533,21 +501,23 @@ int main(int argc, char** argv)
UNLOCK_COUT
socket.close();
// defibrilates if server in blocking accept
LOCK_COUT
cout << "Requesting server quit." << endl;
UNLOCK_COUT
req_serverQuit=true;
boost::asio::connect(socket,target);
socket.close();
if (standalone) {
// defibrilates main server thread if blocked
LOCK_COUT
cout << "Requesting server quit." << endl;
UNLOCK_COUT
req_serverQuit=true;
boost::asio::connect(socket,target);
socket.close();
LOCK_COUT
cout << "Waiting for server shutdown." << endl;
UNLOCK_COUT
if (server_thread!=NULL) {
server_thread->join(); //while (serverActive) ;
delete server_thread;
server_thread=NULL;
LOCK_COUT
cout << "Waiting for server shutdown." << endl;
UNLOCK_COUT
if (server_thread!=NULL) {
server_thread->join(); //while (serverActive) ;
delete server_thread;
server_thread=NULL;
}
}
return 0;