And I Won't Save You from the Rats

October 21st, 2019

The girl hurled over her head a full rubbish bag that was almost half her size, aiming with anger-driven precision at the scurrying rat that simply explored his newfound pile of potential food. She was 7 or 8 at most, a tiny thing with a small frame, dark hair and even darker eyes.

As the bag hit the pile she didn't even care to look if she had hit the rat too or not. She didn't care that much about the rat or about *that* rat. Its unexpected appearance was just the straw that had broken the back of her thoughts turning them rather suddenly from gloomy resignation into sharp insight coloured by despair - hence the anger. Such insight, such despair and out of such a simple task that it had caught her entirely unprepared - if one can ever be prepared for such a thing anyway.

Throwing the rubbish out would be a simple task indeed but not there, not then - simple only in other places, inaccessible places and in other times, long-gone times. Where she was and where she was going to grow up, there was no such thing as a simple task, the environment itself would not permit it. And the complexity of the simplest task was always maddeningly irrational for it didn't come from the task itself but always from the surrounding bits and pieces that stood forever in the way of everything. But it was not even the unexpected and unnecessary complexity of something as banal as throwing the rubbish out that had her despair of everything - it was simply the suddenly obvious, uninterrupted and neverending pattern of brokenness that she had glimpsed abruptly on such a scale that seemed to her to entirely negate any possibility of finding a way out of it, ever.

The throw-out-the-rubbish chore should have been in normal times simply a matter of going with the bag to the building's rubbish chute on the same floor as the flat the girl lived in. But the chute didn't work anymore because someone had thrown down it something that had gotten stuck and nobody seemed to care enough to fix it. And so one had to go downstairs as many floors as was needed, except the lift was of course not quite working, as electricity would go on and off frequently and get one stuck in between the floors. The stairs were pitch dark too, sometimes for lacking light bulbs and sometimes for lacking electricity but at all times for some lack or another. To go up and down those gray, concrete stairs, there was at best of times only a flicker of light coming intermittently - if you knew how to look for it - from the hole between the rails in the middle. The building had at the back a door that led closer to the rubbish dump but the door could not be opened anymore because those not seeing the point of a working rubbish chute did not see the point of an opening door either. And now the rubbish dump at the back of the building had also overflown into a big rubbish mound that attracted - as she had just had the pleasure to discover - some rats to grow and possibly take over the building if they managed perhaps to compete with the cockroaches that had been entrenched in the building's basement for years already.

She quite expected nobody would really mind the rats either, at least not in any way that would make the slightest shred of difference. After all, they hadn't minded the stuck chute, nor the cockroaches, nor the unusable lift, nor the lacking lightbulbs or the ligthbulbs lacking electricity, nor the heating lacking heat, nor the food lacking meat, nor any of the other abundant lackings that made the very substance of daily life there, nor anything at all. That was really the insight that had hit the little girl that day in a visceral way for she hadn't found yet quite fully the words to say it: she was growing among those who had no capacity and no disposition to ever mind effectively anything, no matter how awful or how broken or how entirely insuffereable it would get. Other than perhaps a few more grumbles they just carried on as before, for them everything was equal to anything else and none of it mattered or could possibly matter.

I was once that little girl and every time when an exposed fault is ignored, every time when the choice between fix or live with it broken is made, I see again very vividly the mound of rubbish and the rat, the cockroaches and the pitch dark, the concrete gray wall blocking for hours the way out of the lift's tiny cage, the endless and inescapable string of lackings that end up making the "daily life" of them choosing comfort over painful fixing of whatever is uncovered to be broken.

And now tell me, as in those dear-younger-self fashionable exercises, what exactly would you tell that little girl and mind you that by that point she'd had already stared down "adults" before for talking "comforting" nonsense of the very empty sort.

What exactly will you tell your own child if one day they figure out just why and wherefore all the lackings they experience come from? Or is that really why you won't allow them to do much by themselves: the fear that they will inevitably find out how broken their environment really is?

How My Blog Moved North (to the USA)

October 20th, 2019

On the 6th of October, my blog went offline as a result of what was quickly but adequately branded as the pizmess. The piz(arro)mess started in fact on the 4th of October, as an apparently targeted ddos attack on republican infrastructure including my logger machine hosted with MivoCloud as well as most/all Pizarro-hosted machines. While my Moldova-based provider needed however only a quick email from me to update their rules and mitigate the "attack", the Uruguay-based data centre turned this initial blip into a full-blown catastrophy for Pizarro, nullrouting their IPs for a whole week and acting overall increasingly ineptly over it too.

As the uruguayan noise just increased along the lines of "ra-raaa attack, can't do anything other than nullroute!!", I even pinged again my moldavian provider to get some concrete data as to what terrible thing had hit my logger. And here it is, all of 1.5Gbit/s peak of it, with dump.pcap file attached and coming from just a few IPs really:

The incredible 2019 ddos on logs.ossasepia.com

The incredible 2019 ddos on logs.ossasepia.com

While my logger was therefore quickly back online and happily serving TMSR, my blog and Minigame's servers were not to recover as the pizmess quickly went from bad to worse. As a result, Pizarro, the in-WoT preferred provider of dedicated servers and colocation services went out of business within a week, as its data centre1 proved to have irremediably turned into a scam and a rather inept one at that, involving nullrouting of paying customers' IPs on the basis of no data whatsoever and failed/inexistent cooling systems in place. On the very same data centre, a report less than 2 years old stated the rather opposite "Given the size and ratio of coolers to cabinets there seems to be a healthy amount of excess capacity". In any case, overall the exact speed at which this centre->scam conversion happened is unclear but the whole thing seems to have taken Pizarro management entirely by surprise as there was no plan B in place and nothing to do other than to wheel the data and the hardware out of there as soon as possible, contact local lawyers, file a police complaint and otherwise write the adventure's epitaph: servers for sale, in Uruguay. All of this was done and done timely, to Aaron's credit.

Still, despite all the good intentions, my younghands.club remained unreachable and this affected worst precisely newcomers and learners, the exact sort of situation I could have done without. My blog also remained offline and all my up-to-date backups of it (as of all other data, Minigame's as well as mine, of all sorts) could still not paper over the sinking feeling of atrophiating writing muscle that came with the situation. So I had no choice but to look for a new provider to host both younghands.club and ossasepia.com.

The initial logical2 option was to attempt expanding the contact with Maxim from MivoCloud rather faster than initially contemplated. Responsive as ever, he came in for a talk when asked and was very willing to host republican machines as they come but in the end the whole thing fell through because of his unexpected refusal to actually use his acquired position in the WoT in any meaningful sense. So with this option closed, what else was there to do then to hit the list of ISPs again and start contacting more of them to see if I could by any chance find one I could actually work with. And as this tiresome talking to all sorts of pretend ISPs went on and on with mostly headache to show for it and very little else3, the younghands.club that could not wait anymore was set up with MivoCloud and this blog here finally made it back online only when Stanislav discovered that he actually had all he needed - and cheaper too! - within 20 minutes drive from his very own desk.

So with many thanks to Stanislav for his quick and smooth bringing up of all my blog-data4 on the new Rockchip in the USA, the first thing I did upon getting my blog back was to shudder at the ugly theme I had lived with for lack of anything else to choose from. The thing with crises like this is that they force anyway such an expense of time and effort that in the wake of it I get triggered again by *all* the pending/unsolved/still-broken issues and with an intensity that has deep roots I know only too well about. So I usually weigh very carefully and hold on to acting too quickly on those triggers so as to not end up doing all sorts rather than the most useful and truly needed sorts. Still, I considered that the new home for my new blog could do with a maximum of one hour spent on hammering an existing theme into something I could at least stand slightly better than that green thing.

Funnily enough it turned out that even less than 60 minutes on this task can make quite a difference: the "default" theme with the blue header morphed into what you can see with just a few touches to the .css files (both of them) to change some colours, some fonts and the wasteful padding of single-post pages, as well as a few further touches to .php to put in the server-side selection mechanism and tweak odd bits and pieces so it doesn't look *that* terrible. Hopefully there will be some themes I can choose from before my next "can't stand this anymore" hits again with such intensity.

In other technical terms and at Stanislav's request, I did also a few tests of the new location, here's some data for the hungry reader:

  • From ossasepia.com server (USA), the ftp get aimed at logs.ossasepia.com (Moldova) went like this: 1105154420 bytes received in 539.60 secs (2000.1 kB/s)
  • The other way around, from logs.ossasepia.com server, a wget of a file ~86MB went like this: 100%[======================================>] 89,944,680 131K/s in 10m 11s
  • While the above may look surprising, the issue is not on the USA side I'd think. Here's how the same wget went from my home (UK) to ossasepia.com (USA): 100%[======================================>] 89,944,680 998K/s in 1m 45s

Now that my blog is back up and running on Stanislav-owned iron again, there is of course the whole backlog of write-ups to be done on top of all the crisis-induced tasks plus usual tasks plus new tasks. How do adult people *ever* manage to get bored?


  1. Latecho, of Uruguay 

  2. Not quite ideal though, partially because of grouping again *everything* in a single place and partially because of location (on Internet pipes map rather than purely geographical) and distance from any L1 presence. 

  3. There is in fact a pile of emails to show for it + at least two ISP representatives that made it to register a key with deedbot if not really any further than that. And now I have of course the added task of going again through the pile of emails and doing a write-up of it all, preferably sooner rather than later. I know it and my every-growing list of stuff-to-be-done overflowingly-knows it too, what more can I say about it. 

  4. Thanks to Aaron too, for his packing and sending of data from Uruguay. 

Din discutii cu bataie

October 1st, 2019

Because the forum was searching for this snippet that lived in fact happily in my personal logs until now, here it is shared for all who want to know - why beating, how beating, what sort of beating? To all those questions, there is of course a simple answer: enjoy!

mircea_popescu buna-mea o fost directoare in anii lichidarii analfabetismului. cetateni veneau ca bre, nu ma pune la buche, hai mai bine sa va repar gardu', da-mi ceva sa ma chinui fizic ca cu aia-s invatat macar.

diana_coman mda, cred

mircea_popescu asta nu inseamna ca vietuirea nu-i chin, doar de-aia, ca esti tu invatata cu un chin anumit. tate is.

diana_coman da' in cuvintele nemuritoare ale maica-mii catre o anume profa de fizica de voia sa ma ia cu sila la pregatire din ceva motiv: doamna, eu n-am nevoie sa platesc pe altcineva sa ia fata la bataie daca-i cazul

mircea_popescu ahahaha

mircea_popescu "ce, iti pare ca n-o poci bate io ?!"

diana_coman pai fix aia, da

mircea_popescu seaca faza.

Ossabot's Hoster After 1 Month

September 27th, 2019

After filtering quite a number of hosters back in August this year, I've selected as home for my logger a Moldavian business1 that seemed by far saner than many. While I would normally wait for quite a lot longer to review any provider, Stanislav asked me recently about them (in #o) and so I oblige. In short for the impatient, so far my experience is this: they have been reliable and very prompt; they are willing to do the right thing although at times they need to be asked specifically (ie they will do it but you have to ask for it); they have only Intel dedicated servers (the cheapest is 49EUR /month) but with unlimited traffic (promised by them, I haven't really tested it in any way) and a reasonably stable connection. Since they seem willing and able to learn, I'll take the time to talk to them first and invite them to register a key and come by #ossasepia so that hopefully they can further answer questions and who knows - get further clients. So give this a few days please and I'll update with their response to this, either way. As for the details of my experience with them so far, read on.

The way they made it to the top of my list would be: no idiotic restrictions as far as I could tell, no idiotic requests for data that doesn't belong to them, a reasonably clear description of services offered and prompt+relevant replies to questions asked, accepting payment in BTC. Right from the start they've been very responsive (you can basically have a reasonable conversation via email with them during working hours) and reasonably accommodating, if somewhat in need of clear directions at times. I'm fine with this - from my point of view it qualifies as providing a service.

Initially I took a dedicated server on a monthly basis (for what I consider the absolute minimum initial test-period; as things worked out well, I just switched to yearly basis and so just paid the new invoice for the next year). I asked them for Gentoo on it but specifically with python 2.7 and gcc 4.9 (although it wasn't on their public list) and they replied willing to do it but from their answers it quickly transpired that they weren't all that knowledgeable about what it involves exactly. As I wanted my logger up sooner rather than later, I decided to go ahead with CentOS 6 instead, as a much more straightforward option. To their credit though, from all the signs, they would have tried to do the Gentoo, had I insisted on it (and they never said no in any form).

To get my dedicated server, there was at first a slight confusion as they have this "account" on their website and well, it wasn't quite clear what sort of "account" do I need to make a BTC payment. Happily it turned out that the account is really just for them to have where to send your invoices /group your orders rather than otherwise involved in any way with BTC payment. While I can't say I'm particularly fond of yet another account, it's at least minimal so I let it pass. As to the payment itself, they have a bit of a silly thing: they generate a new address every time you click on the "pay this invoice" button and the interface then starts a 1 hour timer for it too! Nevertheless, one email and one question later they said the sane thing - the timer doesn't matter. So now when I paid for the full year, I simply got the BTC address they gave me2 and made my payment, they waited for network confirmations and once those were in, the invoice was marked as paid and that's that. Isn't it how things should work, anyway?

Once the payment was made, they were very prompt with the delivery - iirc it was that same day or at most the day after. They sent at first the details in plain text via email and without any fingerprint of the server either but once I asked them specifically to regenerate the credentials, add the server's fingerprint and then encrypt everything (here's my public key, use it!), they did it straight away. There was some other minor issue (I can't even recall exactly what it was) that they promptly corrected when I pointed it out to them so all was well.

In terms of uptime and bandwidth, things look fine so far: there wasn't any reset of any sort, I could always connect and otherwise the logger fell down from the chans only twice in one month and one of those was after a netsplit; I already gave in chan some timings for access from the UK that compared favourably with other locations. My needs for this particular machine are not that great and so I didn't really look for anything further than the above. At any rate, if/when I need something else/more I rather expect I'll need to specifically ask them for it but if past experience is anything to go by, they will be willing to do as asked so that works for me.

Overall, my main reservation at the moment in recommending them for business is that one needs to communicate via email and to go through the un-necessary website account thing to order something from them. Hopefully though they actually want more business and so they will make it into the WoT once asked for it, so I can rate them and get them in a position where they can offer further service. Let's see how it goes, at any rate.

UPDATE 30 September 2019: Glad to say that they acted on this as promptly as on everything else - Maxim Mivo registered a key and then joined #ossasepia where he seems to have gotten a new client already.


  1. I can't really give their name since they don't yet have an identity really, seeing how they don't have anybody with a registered key and so I can't rate them. With this as with all the rest, I'll have to ask them though, perhaps they take the sensible route and come in. Update 30/09/2019: meanwhile Maxim Mivo registered a key as CEO of MivoCloud and so I rated him. 

  2. Yes, a proper 1. 

Pretty Petty Particles (Notes on Graphics in Eulora, VI)

September 27th, 2019

As the latest client data hierarchy draft revealed a gaping hole regarding the exact use and requirements of "effects", I've spent those past days diving into the tediousness of "particle systems" - those are the core of CS effects since they are used to simulate rain, snow, explosions, fires, fountains etc. On the bright side, particle systems are actually explained in a bit more detail than other things in the CS manual, mainly because they have been apparently changed quite significantly so the manual's author felt the need to provide examples for using the new code. On the darker side, they are stuffed into the clunky system of various plugins + xml + factories + meshes + shaders + 1001 attributes to set for the smallest thing, so that 3 drops of rain get you sweating and swearing through the usual multiple layers of all-possible-things in slightly-different-ways.

To start with, trying to find a proper place where those particle systems belong in a sane hierarchy of CS items is rather dubious because particle systems are a combination of almost everything in there plus "emitters" and "effectors". And ~everything has to do the dance of factory+instance although each time pretty much everything gets re-set anyway1 so it all feels like an exercise in bureaucratic-coding, to make one's stomach heave anew. Anyway, the core components of particle systems are those:

  1. A non-moving mesh that is the "particle". Like all other non-moving meshes, this can naturally have one or several materials/textures and shaders (with the load of shader variables) but unlike all other non-moving meshes, the geometry is not something one sets explicitly via vertices and triangles and all that - instead, the geometry is fixed and set by the provided "plugin"2 for particle systems! Setting various parameters allows one to tweak this geometry to some extent but that's about it. According to the manual, the existing plugin simply makes all particles rectangles - you can set however their size and their orientation with respect to the camera.
  2. Any number of emitters. As the name suggests, the emitters create and launch about new particles according to another set of parameters. For the same particle system, one can in principle add any number of emitters but there has to be at least one emitter for anything to happen, of course. There are a few types of emitters that differ mainly in the shape that is covered by the launched particles: sphere, box, cylinder, cone.
  3. Any number of effectors. From my tests, those are not even mandatory. They provide some ways to influence the existing particles (usually their movement but supposedly any aspect of them; the manual says that effectors "put different kinds of effects" on particles, "be it physical or non-physical effects"). There are only three available types of effectors: force, lincolor (interpolates the colour of each particle between two values based on the remaining time to live) and forcefield.

Once a particle system is created, the way it works is relatively straightforward: the engine calls on every frame the update loop of each particle system that is visible to the user; the update loop deletes old particles, polls all emitters to emit new particles, polls all effectors to apply their effects and then performs the final transformations if/when such are required. Basically a particle system is designed as a sort of predefined show happening at some place in the world for some specified interval of time with rectangle-shaped actors only (but possibly various costumes via materials).

For practical tests, I've created from code several types of particle systems including "rain", "fountain" and "fire". While the general mechanics of it all seem to work fine and the parameters seem to do indeed what is expected, there is still some weird issue with the materials - all the stuff looks brown-ish, no matter what texture or material is loaded. Since otherwise a material is just a material and it's clearly loading fine for anything else, I quite suspect that the trouble here is the shader: although in principle any shader could be used, there is a specific particle_shader that is used but not really documented anywhere (ie there is the xml of course but that has some variables and possibly references and it is *one* area that I rather avoided to fully get into, so far). Added on top of all previous experience, I'd rather say that sooner or later I will still have to dig shaders too, what can I do. Anyways, at the moment I am mostly interested in having the mechanics in place and figuring out the parameters, so in this sense it's a success, here's some snow and rain falling down on naked girl, at times with erupting particles too:

Euloran Snow - it's more brown than white!

Euloran Snow - it's more brown than white!

Undisturbed euloran woman among erupting stuff and pouring rain.

Undisturbed euloran woman among erupting stuff and pouring rain.

Let it rain with brownish nothings.

Let it rain with brownish nothings.

Given the above, I'll mark the "particle systems (Air)" as explored for now and move on to procedural textures (Water) to see what further catralliard of parameters I find there too. The test of movement for effects (ie following a char or something) is still on the list too but I see it as more general really - since the whole particle system is simply a mesh, having it follow another mesh should be just a matter of giving its position as relative to that rather than absolute. At the moment I'm not sure where exactly would be the best place to do this but I think it requires a bit more consideration because it's possibly a more generally useful thing to have - some items/characters might simply follow others at some point/for some time, anyway.


  1. It would even be hard to keep track of what is same and what is different given how many darned setThis and setThat one calls. 

  2. The plugin's code can be found in CS/plugins/mesh/particles/object/. 

Tedious Takeover, Regulatory Style

September 19th, 2019

Motto: for your own safety and security

In 2017, the UK has enacted a shiny new Act1 that became effective this very year (2019), in April. The core of it is to make it abundantly clear that higher education in the UK has not much left in common with the ancient tradition of focusing on learning and advancing knowledge. Instead, the new Act states clearly that the very term "higher education"2 will by law apply only to those who submit humbly and fully to the newly created Office for Students (OfS) whose stated "four primary regulatory objectives" read:

All students, from all backgrounds, and with the ability and desire to undertake higher education:
1. Are supported to access, succeed in, and progress from, higher education.
2. Receive a high quality academic experience, and their interests are protected while they study or in the event of provider, campus or course closure.
3. Are able to progress into employment or further study, and their qualifications hold their value over time.
4. Receive value for money.

Do you see anywhere in there anything at all about knowledge? Anything at all about personal improvement even? Sure, if you *already* define your "learning" along the lines of "academic experience", your "knowledge" along the lines of "qualifications" and your personal improvement along the lines of "progress into employment or further study", I guess you are plenty served there, fully protected and well looked after. After all, the less "you" there is left, the less trouble you can ever get into. Just progress between these walls here and those walls there - we're building more walls too, don't worry, you'll never have to go outside of any walls really - just stay between the walls and enjoy the... experience, I guess? Oh, it's called academic experience, just so you know, it's all the rage to have one or two or even three of those now, so go for it! And never mind the money either, since you'll receive value for it, the OfS has it written right there, at point 4, ok? Not to mention that having a huge debt will be all the rage by the time you finish the ... experience.

To move further from the above - if you can, because honestly, by this point and under those definitions I already lost all interest in having anything to do with this particular brand of "higher education" - let's see exactly what does this OfS really do and when would you actually have to suffer them around. Perhaps it's just for those institutions that are indeed not independent anyway but fully public-funded and thus perhaps quite rightly saddled with all the attendant indignities? But of course not, no, why stop there! And how *can* there even be - says the bureaucrat arching his eyebrows in extreme surprise - recognised education outside of the state-mandated experience? No, such thing is not to be tollerated3 and therefore, any institution that wants to be able to award its own degrees has to register, bow and bend over for the OfS to consider it at will. Even for that procedure there is some prescribed progression, of course, and while the wad of paper doesn't go quite as far as saying that nothing else than *that* particular form of worship will do, it can't fully keep itself in check either and so makes a note that if the route taken is not the "typically" taken route, then you should talk to them first, before even applying (let's all chant now, the logical why: for your own safety and security!). Just in case you were curious, the "typical" route for an institution applying for its own degree awarding powers is to have been first for at least 4 consecutive years in a validating/franchising agreement with a degree awarding institution.

Trying still to look at more palatable options, I looked first at what exactly is included in "degree" and here it is: anything foundation and bachelor's (aka undergraduate) as well as master's and doctorate. So what's left? Well, you could in principle go for something like "further education" that is supposedly filling the gap between finishing school and going into either higher education or work. But of course, that doesn't have much to do with anything at the end of the day and moreover, if you actually do take in those under 18, you end up in the other (even wider, since more established already) wad of regulatory paper - experience-ensuring for children since they are not classed as adults.

While I read further and further through a lot of tediousness, I really can't summon any reason to further spend time on dissecting it here since there's no benefit I can see from it. Given the above, I'd rather make my own "institution" altogether since dissociating from those4 is a benefit all in itself but if you really see some path that might still be worth to follow in there, please leave a comment.

And if you are here in search of what once used to be called higher education (and is called so no more), have a look at younghands.club and The Pageboy's Pledge and come talk to me.


  1. It's called HERA to stand supposedly for Higher Education and Research Act 

  2. Also related, "reserved" words: university, university college, accredit and derived words, polytechnic, university centre. 

  3. and for very valid reasons, I suspect, since imagine the trouble then - you might get some pesky real thing that you can't control and then what are you going to do?? 

  4. Come to think of it, I'm not even sure that "university" is worth claiming back given its roots; if anything, I suppose I'd go for "academy" but even that is used around here, in the usual maddeningly confusing way, for some sort of school-trusts; overall my already-chosen younghands.club domain stands probably best as it is, after all 

The Pageboy's Pledge

September 18th, 2019

  1. I ask for help to expose and correct my mistakes so that I can learn from them and grow to be a better person.
  2. I commit to my own improvement through training as directed by my Master.
  3. I practice at all times unflinching honesty towards myself, my peers, my betters and my Master.
  4. I open myself up to take in fully and make the most of my Master's feedback whenever gifted and in any form given.
  5. I submit to my Master's judgement at all times.


So help me my own intelligence and cursed be my own stupidity that is holding me back!

Eulora Client Data Hierarchy v2.0

September 14th, 2019

This replaces the previous draft and is based on the new knowledge of client entrails of all sorts as acquired during those past 2 months. It is however still a draft in that it uncovers some new questions (at least new to me) and it requires anyway some feedback and discussion given its scope and crucial position in the SMG Communication Protocol. It's published as it is at this stage and by the promised deadline not because it's "complete and final" but mainly because I need to have this version exposed for further discussion in order to be able to advance it further.

While I was already trying in the previous draft to figure out more clearly the scope and nature of the desired hierarchy, this became clearer only after getting a better understanding of the various data the client uses and especially after further discussion in the SMG boardroom of the protocol specification. The previous observation that there are 3 types of information in there (structure, description, representation) is as correct now as it was then. But meanwhile, as I got to understand better all the different domains involved, the high-level view evolved to this:

  1. Game World
    1. Concrete objects
      1. Terrain
      2. Water
      3. Air
      4. Characters
      5. Structures/Items1.
    2. Abstract objects
      1. Time
      2. Self
      3. Sector
  2. Representation
    1. Graphical
      1. 3D
      2. 2D
      3. Skin/GUI
    2. Audio

Before going further and into the hairier details, it's worth stating the important distinction that the protocol specification makes between the two types of "resources" that the client can ask for:

  1. Files - relevant protocol messages 4.4 File Request and 4.3 File Transfer.
  2. Objects - relevant protocol messages 4.7 Object Request and 4.8 Object Info (ie "Transfer")

The Files are - from the protocol's point of view - "big" resources that never contain other resources. Files are referenced by their full name that works therefore exactly like an id (although a text-id rather than a numerical id).

The "objects" are - from the protocol's point of view - "small" resources of a potentially composite sort. This means specifically two things: any object will always fit into one single message; an object may contain references to any number of other resources (ie references to other objects and/or to any number of files). An object is given (via a 4.8 message) as a list of tuples (id:type). Each such tuple is the reference (the "id" part) to one "property" of the object, where the term property is quite generic: any object can be at some time or another a "property" of another object. Note also that "id" is not necessarily a numeric id - a filename (with full path included, where relevant) is effectively the "id" of the actual file.

The hierarchy starts with the single object that has no id (otherwise put it has the "null" value as id). Since all things have to start from somewhere, so does Eulora's language of knowledge - in the beginning, it is always "null". If you think of the hierarchy correctly as a tree, this object with "null" as id is the root from which there can be ultimately any number of levels - the hierarchy is *not* restricted on either direction (ie any node can have in principle any number of children and any path may be arbitrarely long). The leaf nodes will *always* have "Final" as given type in the tuple (id:type). The id in the tuple (id:type) of a leaf node is either a filename (ie the id of a file, one can think of this as value given by reference) or otherwise a value that is used directly as it is, as data (e.g. helmet.png:Final or 5:Final). All values given at a leaf node will be one of the following basic types:

The root of all the world (the object with "null" as id) is the object that the server sends (via a 4.6 World Bulletin message) in response to an Object Request (4.7) that contains an unknown/non-existent object id. The hierarchy as I managed to flesh it out so far is given as id:type with comments after > :

  1. Root > there is only ONE object of this type and that object has id "null"

    1. Top_Location_ID : Sector > current sector; player's character is somewhere in the subtree of this object (eg may be in a room that is in a house in this sector, perhaps).
    2. Self_Info_ID : Self > id of the abstract object, not the id of the player's concrete character object.
    3. Current_Date_ID : Date > euloran date
    4. Current_Time_ID : Time > euloran time
    5. Client_Skin_ID : ModSkin > graphical user interface resources
  2. Sector

    1. CurrentNameID : Name

      • Value (text): Final
    2. Terrain_ID : Terrain > the heightmap (+ material palette)
    3. Air_ID : Air > ambiental light and weather (?)
    4. (Light_ID : Light)* > NB: zero or more; those are purely sources of light (NOT ambiental light which is a property of Air), without physical representation other than the light itself.
    5. (Water_ID : Water)* > bodies of water
    6. (Character_ID : Character)* > anything that is active/can move;
    7. (Structure_ID : Structure/Item)* > anything that is passive/can't move and is not terrain/air/water/weather
  3. Self > this includes all the stuff that is specific to self (ie known only about own Character) as opposed to the generic info given via Character type (ie info available for all characters encountered, whether self or not)

    1. CurrentPlayer_ID : Character > player's actual character with data that everyone can access/see
    2. Current_Loc_ID : LocID > should the location ID be here? (otherwise in principle client can fully search the tree until it finds CurrentPlayerID as contained in some location)

      • Value (uint32): Final
    3. Date_Of_Birth_ID : DOB

      • Value (date) : Final
    4. Vitals_Profile_ID : VitalsProfile
    5. Skills_Profile_ID : SkillsProfile
    6. Inventory_ID : Inventory
    7. Equipment_ID : Equipment
  4. Inventory

    1. (Item_ID : Structure/Item)*
  5. Equipment > How is equipment different really from Inventory? I can't see any real reason to make it a separate type. "Equip" is an action and as such it will fail if the item doesn't "fit" the destination, be it because it's not equippable or whatever. Similarly, the "how it looks" is a matter of checking what is in some slots if one so wants. The only thing: the meaning of "positions" in inventory should be defined, at least for those that have a specific meaning beyond "in the bag".

    1. (ItemID : Structure/Item)*
  6. Date > this could be in principle simply unixtime number but that wouldn't match well/easily with custom year/month sizes (?) + presumably custom month names rather than numbers (?)

    1. Year_ID : Year
      • Value (text) : Final > should those be numbers?
    2. Month_ID : Month
      • Value (text) : Final > should those be numbers?
    3. Day_Of_Week_ID : DoW
      • Value (text) : Final > should those be numbers?
  7. Time

    1. Hour_ID : Hour
      • Value (uint8) : Final
    2. Minute_ID : Minute
      • Value (uint8) : Final
    3. Second_ID : Second
      • Value (uint8) : Final
  8. ModSkin > should this cover *also* layouts & windows & UI components or only strictly "art" resources? If it's the later, in principle it's simply a list of images (with at most width, height, alpha, transparency)??

    1. (UI_Art_ID : UI_Image | UI_Spritesheet) *
  9. UI_Image

    1. (Name_ID : Name)? > CS uses everywhere names for IDs and sprite sheets won't be fine with filename as name for each sprite; onth perhaps client should just generate its own "names" out of object id and/or filename if it needs them?

      • Value (text) : Final
    2. Size_2D_ID : Size

      • Value (size2d) : Final
    3. Transp_ID : Transparency

      • Value (rgb) : Final
    4. Alpha_ID : Alpha_Lvl

      • Value (float) : Final
    5. File_ID : Image > should all be .dds or .png or fixed format?

      • Ref (text) : Final
  10. UI_Spritesheet

    1. UI_Image_ID : UI_Image > for the sheet as a whole, it still has all the details
    2. (UI_Sprite)+
  11. UI_Sprite

    1. (Pos_ID : Position)? > for sprite sheets - position in parent image

      • Value (position) : Final
    2. (Name_ID : Name)? > CS uses everywhere names for IDs and sprite sheets won't be fine with filename as name for each sprite; onth perhaps client should just generate its own "names" out of object id and/or filename/whatever if it needs them?

      • Value (text) : Final
  12. VitalsProfile

    1. (VitalID : Vital)*
  13. Vital

    1. Name_ID : Name
      • Value (text) : Final
    2. Current_Value_ID : CurrentValue
      • Value (uint8) : Final > assuming that those are still given as % of max
  14. Skills_Profile

    1. (Skill_Group_ID : SkillGroup)*
  15. Skill_Group

    1. NameID : Name
      • Value (text): Final
    2. (Skill_ID : Skill)*
  16. Skill

    1. Name_ID : Name
      • Value (text): Final
    2. Rank_ID : Rank
      • Value (uint64): Final
    3. Practice_ID : Practice
      • Value (uint8) : Final

      > assuming given as %

    4. Knowledge_ID : Knowledge
      • Value (uint8) : Final

      > assuming given as %

  17. Character

    1. Name_ID : Name
      • Value (text): Final
    2. Sex_ID : Sex > is this given and in what form? is it known for anyone or just for self?
      • Value (uint8): Final
    3. Position_ID : Pos
      • Value (position): Final
    4. Rotation_ID : Rot
      • Value (rotation): Final
    5. Model_3D_ID : ModCal3D
    6. (Model_2D_ID : Mod2D)? > 0 or 1
    7. (Model_Audio_ID : ModAudio)? > 0 or 1
    8. (Model_Effects_ID : ModEffects)? > 0 or 1
  18. Structure/Item > the difference between structures and items is minimal to the point of inexistent (eg "structures" can't be picked up perhaps, but that's not a property - simply a response to an attempted action and as such of no interest/relevance here!; or structures will have stack count = 1 but that doesn't mean that they don't have stack count...)

    1. Name_ID : Name
      • Value (text): Final
    2. Stack_Count_ID : StackCount > this will just be 1 for houses / some cases.
      • Value (uint64): Final
    3. Quality_ID : Quality > this may be called "durability" for eg tools or houses but it's same thing anyway.
      • Value (uint64): Final
    4. Position_ID : Pos
      • Value (position): Final
    5. (Model_3D_ID : ModCal3D)? > ONE of the models 3d/2d should be present in general
    6. (Model_2D_ID : Mod2D)? > 0 or 1
    7. (Model_Audio_ID : ModAudio)? > 0 or 1
    8. (Model_Effects_ID : ModEffects)? > 0 or 1
  19. Terrain

    1. NameID : Name
      • Value (text): Final
    2. Position_ID : Pos
      • Value (position): Final
    3. Height_Map_ID : Heightmap > NB: while both materialmap and heightmap are images (and even of same type + same size, listing them as "IMAGE" type means that the role (i.e. which one is Heightmap and which one is MaterialMap should be defined somewhere else - would that be better/how?)
      • Ref (text): Final

      > filename, hence "Ref", currently "Island.png"

    4. Material_Map_ID : Materialmap
      • Ref (text): Final

      > filename, hence "Ref", currently "Island_alpha.png"

    5. (Material_ID : Material)* > material palette to use (eg sand, grass, stone)
  20. Air

    1. AmbientLightID : AmbientLight > all lights should be "dynamic" or at any rate the static/dynamic distinction is entirely client-side concern ; currently those values are given at different "times of day" + interpolated by client in between, but I don't see the *need* for hours in here; client can decide on its own if /when it wants to sample this and what/whether to interpolate or do anything else with the values it gets.
      • Value (rgb) : Final
    2. Weather_ID : Weather
  21. Water > is this needed as separate type? CS has 4 types of procedural textures: fire, water, dots, plasma
    > therefore "water" could simply be in principle an item/structure with the "water" texture applied - TO CHECK.

    1. Item_ID : Structure/Item
  22. Weather > CS uses "particle systems" for this sort of thing (i.e. actual snow/rain)
    > as such, those could be just part of the "sector" at some point + corresponding changes to light & sky, if any. TO CHECK
    > however, there can be perhaps the point of having this separate to set specific params such as emission rate, velocity etc. ?

    1. Particle_Syst_ID: Particle_System > if going this route, this is TBF
  23. ModCal3D > aka moving/character stuff

    1. BB_Size_ID : BoundingBox > this is used for collision detection

      • Value (size3d) : Final
    2. Skeleton_ID : Skeleton > this is MANDATORY; all moving stuff have to have a skeleton

      • Ref (text) : Final

      > this is a .csf file for now; should the format be a further level/property?

    3. (Animation_ID : ModAnim)* > a character may have any number of animations
    4. (Submesh_ID : ModMesh)* > parts/subparts of the model; NB: atm sockets is still not used/unclear!
    5. Scale_ID : Scale > intended scale of the model, this is a transformation to apply before use

      • Value (float) : Final
    6. Translation_ID : Trans > pre-transform to apply, translation; same as for scale - could be standard and therefore spec not needed?

      • Value (3xfloat): Final
    7. Rotation_ID : Trans > pre-transform, rotation; same std issue as above.

      • Value (4xfloat): Final > (x,y,z,angle)
    8. RotX_ID : RotX > IF the model should be pre-rotated along the x-axis; again, should be std and be done with. Default is true

      • Value (boolean): Final
    9. FlipTex_ID : FlipTex > whether v coordinates of texture should be flipped (i.e. whether 0,0 in texture space should be top left or bottom left); default is false

      • Value (boolean): Final
  24. ModAnim

    1. Name_ID : Name > name is used as an id by CS... eg "walk", "run", "jump"

      • Value (text) : Final
    2. File_ID : File > this is a .caf file for now; should format be a deeper level?

      • Ref (text) : Final
    3. Type_ID : TypeAnim

      • Value (uint8) : Final > idle, travel, cycle, action, none, style_cycle currently from CS&PS - WTF?? do we even want such a thing?
    4. Vel_ID : Velocity
    5. Time_ID : Interval > this is "interval for idle or override actions", in seconds

      • Value (2xfloat): Final
    6. Idle%_ID : Idle% > this is "probability (as %) of this action being the overriding action"

      • Value (float) : Final
  25. Velocity > this is for animations

    1. Base_ID : Base_Vel > speed of translation when animation is used on its own

      • Value (float) : Final
    2. MinVel_ID : Min_Vel

      • Value (float) : Final
    3. MaxVel_ID : Base_Vel > min and max are used by CS's internal "blender" to get what precise speed is required at one point or another

      • Value (float) : Final
  26. ModMesh

    1. MeshFile_ID : MeshFile > format is .cmf ; should format be a lower level?

      • Ref (text) : Final
    2. Size_ID : Size > is this actually mandatory/needed here? Can't quite yet tell.

      • Value (size3d) : Final
    3. Name_ID : Name > name of this part of the model, eg "Head", "Neck", "Left_Arm"

      • Value (text) : Final
    4. Material_ID : Material > CS allows several materials mixed on a mesh (though on occasion with this sort of thing it "allows" while at the same time complaininig if too many textures or too many this and too many that) but I'd stick to ONE material only.
  27. Mod3DGeneric > aka structure/item (non-moving)

    1. Material_ID : Material > while several materials can in principle be used, I'd rather stick to ONE material since *that* can combine several textures anyway.
    2. (Vertice_ID : Vertex)* > one vertex as a minimum

      • Value (position) : Final > this is given in model's own coordinate space
    3. (Triangle_ID : Triangle)* > each triangle is given as (i1,i2,i3) where i1-3 are indices of the vertices given previously

      • Value (3xuint64): Final
    4. (Normal_ID : Normal)* > there should be one normal vector given for *each* vertex

      • Value (3xfloat) : Final
    5. (Colour_ID : RGBA)* > there should be the colour given for *each* vertex

      • Value (4xfloat) : Final > this means r,g,b and alpha channel
    6. (Texture_Map_ID : TexMap)* > there should be mapping from each vertex to a texture point (ie u,w coords)

      • Value (2xuint) : Final > these are coordinates in the 2d, discrete space of the texture
  28. Mod2D

    1. Texture_ID : Texture > NB: this currently is "texture2d" but it's unclear if the distinction is worth much (ALL textures are anyway 2d images, ffs)
    2. Transparent_ID : rgb

      • Value (3xfloat) : Final
    3. Alpha_ID : Alpha > this is int in the current code, hm.

      • Value (int8) : Final
    4. Pos_ID : position

      • Value (3xfloat) : Final
    5. Size_ID : Size > height and width

      • Value (2xint) : Final
  29. Material

    1. Name_ID : Name > CS uses "names" in fact as IDs; so there can be several materials with same texture/file/data but different names...

      • Value (text) : Final
    2. Texture_ID : Texture > CS works with materials (it wraps any plain texture into a material anyway)
    3. (Shader_ID : Shader)* > a material CAN have several shaders applied.
    4. (ShaderVar_ID : ShaderVar)* > those are used *across* shaders to customise them, hence put here as separate, ugh; I think though that they belong more logically as a property of each Shader.
  30. Texture > CS supports: png, tga, bmp, jpg, dds, gif, mng, jng; common use given: png/tga for textures with alpha; jpg for those without; "best" = dds because it stores mipmaps directly + no need for additional steps (for a png there is uncompressing + mipmaps calc + recompressing to upload; a dds is directly uploaded to graphics hardware)
    > There are ALSO, "texture classes" but it's totally unclear if they bring anything useful or if they are anyway a server concern at all; from the manual (p. 331/644): texture class = collection of settings controlling how a texture is uploaded to the Graphics hardware (e.g. lookup, normalmap, nocompress) + "adding semantics".

    1. Name_ID : Name

      • Value (text) : Final
    2. Image_ID : TexImage > at this stage it's unclear if stuff like size should be given explicitly since it should rather be either extracted from the file itself (?) or default/predefined (?)

      • Ref (text) : Final
  31. Shader

    1. Name_ID : Name

      • Value (text) : Final
    2. ShaderTypeID : Name > ugh; those are again predefined CS stuff/available shader types...
    3. File_ID : File

      • Ref (text) : Final

      > filename containing the shader description; atm those are a bunch of xml files, full of dependencies & referencing one another + cs-specific.

  32. ShaderVar

    1. Name_ID : Name > NB: those names need to match what shaders (those xml files) know/expect, for anything to work...

      • Value (text) : Final
    2. Value_ID : Texture|Float|2xFloat|3xFloat > the value of the shader variable has one of those types

      • Value : Final
  33. Light > ALL lights are "dynamic" since they can always change/be added/removed etc.

    1. Name_ID : Name

      • Value (text) : Final
    2. CentreID : Centre

      • Value (3xfloat): Final
    3. ColourID : rgb

      • Value (3xfloat): Final
    4. AttenuationID : Attenuation > "type" of attenuation (?)

      • Value (uint8) : Final
    5. RadiusID : Radius

      • Value (uint16) : Final

As full of holes and possibly over-wordy and all that as the above draft finds itself, it was still quite the toil to extract. Nevertheless, extracted and written down it had to be as I couldn't quite move any further without this step. Now that it's pinned down, I can go through it and discuss the questions/issues that are still unclear throughout. There are also a few aspects that are currently still entirely missing (not that the rest is guaranteed to be complete/final), namely:

  1. Some meta resources - most notably authorship of art files - are still missing entirely. I'd rather discuss/iterate first those concrete (relatively) parts extracted from client-entrails before moving on and fixing the details of that, since it's more likely to be actually easier anyway as it's way more clearly and sanely defined to start with.
  2. ModAudio - the definition of this is still missing as I never even bothered yet to get the SoundPlugin to work at all. Perhaps it can be added/fleshed out later on and then clients that know it / want it will use it, while the rest will simply ignore it as an unknown/un-usable part.
  3. ModEffects - this is also still missing but unlike the audio part, this could be more readily investigated and fleshed out more, by figuring out how to load/create effects from code directly, similar to the previous work on characters for instance.
  4. Water - this requires an investigation into creating water bodies from the code directly; specifically: some practical experience using CS's procedural textures and some tests to see if/to what extent this could/couldn't be folded into structure/item
  5. Weather - this requires an investigation into CS's particle systems at the very least (for snow/rain/etc) and some more reflection + testing to check if it makes perhaps more sense to fold this into Air anyway.

  1. This is just one type, the name is given like this to make it clear that both "items" such as an axe or a flower and "structures" such as a house or a bridge are in here. Basically anything that is not terrain/water/air and can't move by itself is in here (if it can move by itself then it's in Characters)  

  2. NB: CS uses floats, with 1,1,1 for white and 0,0,0 for black. 

A Summer's Summary and Next Steps in Eulora

September 5th, 2019

Coming back from any holidays, no matter how short, means that I spend initially a few days simply with the task of picking up again each and every bit of work that I put on hold while I was away. Note that I didn't say "dropped for the holidays" but rather specifically put on hold in a prepared manner so that picking it up again is not a horrendous chore but rather an opportunity to re-load the context with a fresher mind. And this makes it also a good moment to review the work done over the past months and state the next steps just as I usually do anyway for my own benefit before setting to do any work. The only difference this time is that I'm publishing here this whole summary of work done + work in line to be done next, so that anyone interested can follow along. Why wouldn't I publish it anyway?

May was spent on two main pieces of work:

  1. A working initial1 implementation (both on client and on server side) of the SMG protocol parts that are already clearly defined, namely network communication, account request/creation, serpent keys request & management, file request & transfer. This part meant Ada implementation of the protocol but also wrestling the legacy Eulora client into using the network communication structures of SMG Comms as encapsulated in the standalone Ada lib called EuCore. It also included some server-side work so that the end result is proper communication: the client can now ask for a new Eulora account and the server will reply according to SMG Comms; the client can also use its already established Serpent keys to communicate with the server and the server will reply accordingly. As required part of this work, a broad mapping of the client and its dependencies had to be done as well and basic docs for the client were published.
  2. The initial design of client logic for communicating with the server i.e. moving up on to how to use the messages that the protocol (and the implementation at point 1 above) makes available. This involved more reading, thinking, discussing and structuring than coding. The concrete result is a clear client strategy for knowledge acquisition and a very basic initial skeleton of its implementation. However, as the *structure* of the knowledge to be acquired was not yet defined or even fully clear, the next steps (see June below) had to focus on clarifying that, before the implementation can be pushed any further.

June started with fleshing out the hierarchy of data in Eulora as an initial draft capturing the relevant knowledge so far. This helped clearly identify the big areas that required further detailed investigation, most notably the graphics part where neither the required building blocks nor the specific client approach were yet known in enough detail to allow any meaningful attempt to extract a relevant data hierarchy. So the rest of June was spent on figuring out the graphics part: acquiring a better theoretical understanding through study of the reference book for computer graphics2 and at the same time acquiring also a very practical knowledge of how things are done by first mapping broadly (and then ripping apart) the existing approach as it found itself spread and scattered through the legacy client, several plugins of the same and the several plugins more of CrystalSpace (CS) + the code of external libraries (cal3d especially). By the end of the month, the better understanding of the whole graphics part and the practical experience with it resulted in a working initial example of loading some specific type of graphics object and a clear structure of the notions involved. This structure doubles as the map to follow for the next steps towards making the client able to load everything on demand.

July focused entirely on graphics in Eulora, figuring out one by one and implementing a prototype loader for each of the sections in the map written at the end of June:

  1. Loading a static (incapable of movement) object given through its list of vertices, normals at vertices, colours at vertices, texture mappings at vertices and triangles that make its faces. This includes already loading factories and textures.
  2. Loading the landscape aka loading the terrain given through its heightmap and material palette. This includes also loading lights, materials and shaders. The whole was pursued only to the extent that the terrain and materials were indeed loaded as specified by the heightmap + material palette but without fully aiming to solve other potential issues such as the "mirror" effect that is more related to lighting and - possibly - some material or shader properties.
  3. Loading a character made of several parts that can in principle change on the fly. This part was pursued for now only to the extent that the character is loaded and shown + answers the player's control but without fully going into the details of equip/dequip, actions and the full extent of changing bits and parts.

August was a bit split, with the holidays in the middle:

  1. At the beginning of the month, I continued the work on graphics but moved from the 3D issues to 2D, namely the user interface with all the different icons and images and various bits that are sometimes known as the "skin" of a client. This required a deep dive into yet another plugin of the legacy client, the widgeting PAWS.
  2. At the end of the month, I started working on writing down the 2nd draft version of the client data hierarchy integrating the results of all the work on graphics + all the pondering and figuring out done throughout the month + the further discussions and clarifications in the SMG boardroom on the desired working of Eulora's communication protocol. This is still in the works currently but I plan to publish it for discussion as soon as I've got down all that I have so far and certainly no later than the end of next week (ie no later than 15th of September).

The current plan for September and beyond is this:

  1. Write and publish for discussion/revision the deeply revised (re-written really) draft of client data hierarchy. Deadline is 15th of September.
  2. Pending feedback and discussions, possibly dive again for more details if needed and/or revise further the data hierarchy, if/as required. This is a crucial part for moving forwards but it's also one that once fixed will be very costly to change.
  3. Work on the implementation of the client and server-side pieces of the SMG protocol that are still missing, as soon as they are set/clarified. At the moment, they are listed broadly and in this order: client-side data storage (aka cache, of which currently there is only a skeleton, pending better understanding of what the data is going to be exactly), object request/reply, client actions, full client logic for knowledge acquisition and storage, full client loading/use of local data cache, client and server management of own keys.

  1. to be refined/reviewed as other parts such as key storage and bootstrapping become clear 

  2. Foley, J.D., van Dam, A., Feiner, S.K. and Hughes, J.F., "Computer Graphics: Principles and Practice", 2nd ed., Addison-Wesley 

Ossabot and Its Flask of Python 2.7 on CentOS 6

September 2nd, 2019

Ossabot is a clone of Stanislav's logger, consisting of 2 separate parts:

  1. An IRC bot that connects to specified channels and records everything it sees to a local Postgres database.
  2. A "reader" that takes everything from the database and formats it as handy html pages of the sort you can admire at http://logs.ossasepia.com.

The main reason to run a logger in the first place is simply that I quite need it in order to keep track of and reference conversations in my #ossasepia channel. But on top of this and as mentioned previously, providing a public logger for tmsr channels is a basic contribution and one where redundancy is key in the long term. Not to mention that running a bot as part of a synchronised fleet is the closest concrete step I can see at the moment towards Gossipd - as soon as you stop to consider the issue of how to synchronize with others, you stumble towards/upon Gossipd quite inevitably, even if you had no previous idea as to what that was. In one word, running a logger is needed, useful and a stepping stone in the desired direction so it jumped to the front of the (long) queue of work waiting to be done.

For lack of a better option, my logger clone is currently running on CentOS 6. For once, it turned out that my choice of environment was too old even for republican code - the logger and especially its dependencies1 require Python 2.7 and Postgres 9 or 10 while CentOS 6 runs with Python 2.6 and Postgres 8 as default version. Given that the logger had been previously deployed and tested only on Gentoo and combined with the fact that software versions are rather meaningless across different environments, the initial attempt was an exercise in frustration that nearly ended in total abort of the attempt to cross the Gentoo-CentOS divide. Nevertheless, a second attempt was successful, taking advantage of the experience and of a different set of version numbers graciously made public by lobbes. Here's what it took to have Ossabot running on CentOS 6:

  1. Postgres 9.6 and related packages (-devel, -contrib2 ) installed, configured, initialised and started as a service:
    sudo rpm -Uvh http://yum.postgresql.org/9.6/redhat/rhel-6-x86_64/pgdg-redhat96-9.6-3.noarch.rpm
    
    sudo yum install postgresql96-server postgresql96
    Installed:
      postgresql96.x86_64 0:9.6.15-1PGDG.rhel6
      postgresql96-server.x86_64 0:9.6.15-1PGDG.rhel6                                         
    
    Dependency Installed:
      postgresql96-libs.x86_64 0:9.6.15-1PGDG.rhel6        
    
    sudo yum install postgresql96-devel postgresql96-contrib
    
    Installed:
      postgresql96-contrib.x86_64 0:9.6.15-1PGDG.rhel6
      postgresql96-devel.x86_64 0:9.6.15-1PGDG.rhel6
    
    sudo service postgresql-9.6 initdb
    sudo service postgresql-9.6 start
    sudo chkconfig postgresql-9.6 on
    

    The path for pg_config was for some reason not correctly set/updated when installing the 9.6 as opposed to default 8 Postgres, hence:

    sudo ln -s /usr/pgsql-9.6/bin/pg_config /usr/sbin/pg_config
    
  2. Creating the db and user for the bot according to its handy README:
    # su - postgres
    -bash-4.1$ psql
    psql (9.6.15)
    Type "help" for help.
    
    postgres=# create user ossabot createdb;
    CREATE ROLE
    postgres=# alter role ossabot superuser;
    ALTER ROLE
    postgres=# create database ossalog;
    CREATE DATABASE
    postgres=# grant all privileges on database ossalog to ossabot;
    GRANT
    
  3. To set local connections to Postgres as trusted so that the various scripts may run without requiring passwords/authentication:

    sudo nano /var/lib/pgsql/data/pg_hba.conf
    changed in pg_hba.conf (trust for local connections)
    sudo service postgresql-9.6 restart
    
  4. And creating the database for the logger, according to its README, simply run from logger's dir:

    sh init_db.sh
    
  5. The first dependency of the bot is psycopg2 that works fine when installing the default system version, i.e. simply:

    sudo yum install python-psycopg2
    
  6. For Python 2.7 on CentOS 6, one needs the software collections (scl) repository:
    sudo yum install centos-release-scl
    sudo yum install python27
    
  7. Once scl and python27 are installed, the best approach is to enable it in a separate session of its own, to avoid mixing stuff and going nuts. For example:
    $ scl enable python27 bash
    $ python --version
    Python 2.7.16
    

    The scl will install a whole bunch of executables specifically for the Python2.7 environment. It's unclear to me how the exact place of those is chosen and I didn't bother to dig that up but at any rate, on my machine at least it ended up in /opt/rh/python27 so that the bin dir in there contained for instance:

    $ ls /opt/rh/python27/root/usr/bin/
    easy_install      pydoc             python-config       rst2s5          sphinx-quickstart
    easy_install-2.7  pygmentize        rst2html            rst2xetex       virtualenv
    nosetests         python            rst2latex           rst2xml         virtualenv-2.7
    nosetests-2.7     python2           rst2man             rstpep2html     wheel
    pip               python2.7         rst2odt             sphinx-apidoc
    pip2              python2.7-config  rst2odt_prepstyles  sphinx-autogen
    pip2.7            python2-config    rst2pseudoxml       sphinx-build
    
  8. Within the Python2.7 enabled session, you can start installing the various dependencies required by the bot, specifying the precise version required (note the export of LD_LIBRARY_PATH when sudo-ing):
    sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH ./pip2.7 install Flask==0.12.2
    Successfully installed Flask-0.12.2 Jinja2-2.10.1 MarkupSafe-1.1.1 Werkzeug-0.15.5 itsdangerous-1.1.0
    
    sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH ./pip2.7 install requests
    Successfully installed certifi-2019.6.16 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.3
    
  9. With all the above installed (and the unused cache stuff removed from the bot's code), the eat_dump.py, reader.py and bot.py finally run, hooray! Note that you might want an up-to-date dump from one of the older bots to get historical data. If you use such a dump, you'll need to change manually in it the database user name to match what you have (or the restore/import will fail). Still, you need now to take care of installing and configuring Apache (or similar) too:

    sudo yum install httpd
    sudo nano /etc/httpd/conf/httpd.conf
    

    To configure virtual hosts on apache, you need to change the httpd.conf file above, adding for instance:

    < VirtualHost *:80 >
      ServerName logs.ossasepia.com
      KeepAlive On
      ProxyPreserveHost On
      ProxyPass "/" http://127.0.0.1:5002/
      ProxyPassReverse / http://127.0.0.1:5002/
    < / VirtualHost >
     

    And then start Apache and set it so it starts automatically on reboot:

    sudo service httpd start
    chkconfig httpd on
    
  10. The last step is to write scripts to backup the database and to start the bot + reader parts of the logger as well as set up cron jobs to call those scripts. Note that the scl use means that scripts for starting the bot/reader on CentOS will have to first enable python27, for instance:

    scl enable python27 "python /home/youruser/bot.sh /home/youruser/ossabot.conf >> /home/youruser/bot_log.out"
    

As it turns out, standing up the logger on CentOS 6 is an overnight success, quite literally. The above steps should hopefully make it more of an 1-hour task but if they don't, kindly let me know in the comments below. Meanwhile the bot has been running quite nicely and even turned out some interesting issues regarding loglines numbering and sync between several bots. Interesting means of course that they aren't yet solved either so just in case you were looking for something to do, here's your chance.

The code of the logotron is mirrored together with Stan's and my own signatures, on my Reference Code page.


  1. My full list as gathered from the installation notes on CentOS is this: postgresql96-server, postgresql96, postgresql96-libs, postgresql96-devel, postgresql96-contrib, python-psycopg2, python27 (centos-release-scl), Flask (Jinja2, MarkupSafe, Werkzeug, itsdangerous), requests (idna, chardet, certifi, urllib3). Infuriatingly, the python uninstaller does *not* care about the very dependencies that the python installer brought in so if you want to uninstall stuff, you need to do it manually for *all* the above packages. Such progress, such automation, such (w)ow. 

  2. NB: those are needed e.g. -contrib contains the pg_trgm extension that provides fuzzy string matching and is used by the logger