Ossa Sepia

September 19, 2019

Tedious Takeover, Regulatory Style

Filed under: Dark Modern Ages, Outreach — Diana Coman @ 11:23 a.m.

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 

September 18, 2019

The Pageboy's Pledge

Filed under: Dark Modern Ages, Outreach — Diana Coman @ 7:11 a.m.

  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!

September 14, 2019

Eulora Client Data Hierarchy v2.0

Filed under: Eulora — Diana Coman @ 9:38 p.m.

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. 

September 5, 2019

A Summer's Summary and Next Steps in Eulora

Filed under: Coding, Eulora — Diana Coman @ 11:34 a.m.

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 

September 2, 2019

Ossabot and Its Flask of Python 2.7 on CentOS 6

Filed under: Coding — Diana Coman @ 7:57 p.m.

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 

August 25, 2019

The New Old Vilnius of 2019

Filed under: Lyf, Tgdyk tgdyk — Diana Coman @ 3:48 p.m.

They have this thing in Lithuania that they strive to rebuild the past in the most literal, concrete and visible way they can, bricks and mortar and shiny new paint at the ready as if that's what matters and where the essence is - in the very first layer that meets the least discerning eye and nowhere else. And funnily enough the rebuilding of the past sits side by side with failing to take care of the present1 but enthusiastically building for the future past just next to it, so that it all looks - depending on where you turn - either decrepit or ultra-shiny among new-old:

Decrepit building at the top of the hill in central Vilnius. Or looking up to see what you are all headed to.

Decrepit building at the top of the hill in central Vilnius. Or looking up to see what you are all headed to.

The shiny new dwarfing the not-so-shiny old in the front. Or looking the other way - down the hill, away from the decrepit building at the top.

The shiny new dwarfing the not-so-shiny old in the front. Or looking the other way - down the hill, away from the decrepit building at the top.

As to the rebuilding of the past, there's no more trace of the red road in Vilnius2 but the new old castle is fully completed, a white building with small windows next to the mound where the ruins used to be in the very centre of the town behind the other white building with fancy windows and a lot of guys on top holding on to huge crosses. Essentially holding on to their catholicism I suppose, in the very literal and concrete way that seems to be specific to the place. In any case, the completed rebuilding of the past from one ruined tower to a whole "palace" further includes a black statue that can proudly compete with Romanian incompetence at building monuments of this sort. Apparently it's called all sorts of mocking names by locals who focus on the guy's position but I find the "horse" just as weird - as if it were pushing the man over the side of that plinth and into the plazza below:

The horse pushing Gediminas down from his monument.

The horse pushing Gediminas down from his monument.

Just so you don't end up thinking that this rebuilding of monuments and all things past is a Vilnius-only thing or even a modern-only thing or even a focused-on-some-specific-past-only thing, there's also the castle at Trakai as an earlier example of the same approach - if by other masters - in those lands: while there was once a castle there, what you can see nowadays is at best a reconstruction and more to the point a fancy and a pretense really. The history of the place mentions a gradual building and addition of defenses and features while the place held military significance3 followed by similarly gradual falling into disuse and disrepair as its usefulness dwindled in the 17th century. Not a bad life for a castle after all and arguably a rather honorable one to start off as a little fortress on an island, to grow and expand, to serve in all ways possible from an outpost to a dungeon to a royal summer residence and then to rest its weary ruins surrounded by the same blue waters that for all their daily change of colours turned out to have changed so very little by comparison. I've seen photos of the place in the 1870s and I've seen a picture of it from a few years earlier and I'd have rather visited those honest ruins than the reconstructed tourist-attraction in castle-shape for all its prettiness and all its exhibits. Still, one visits always the castle that is rather than the castle that was and there's little point in faulting locals for rebuilding a castle now precisely to bring in the paying hordes while only a few centuries ago they had built a castle to keep away the armed hordes:

The ever-changing Trakai water that stays apparently as it was.

The ever-changing Trakai water that stays apparently as it was.

Tourist trap in the shape of a old castle that used to be on those same islands at Trakai, in other times, in other lives.

Tourist trap in the shape of an old castle that used to be on those same islands at Trakai, in other times, with other lives.

An old chess set exhibited in the castle at Trakai.

An old chess set exhibited in the castle at Trakai.

How did the lion go through the wall?

How did the lion go through the wall?

And so I took the child to Trakai and showed him around the whole place, reconstructed castle included and he was delighted that there was a moat and there were boats and it was truly "on an island" as it's apparently correct and proper for a castle in his mind. The walls and unexpected ends were sort of all right too, at least for... a bit:

The very funny walls of this castle!

The very funny walls of this castle!

The child found the castle smelly inside and it was indeed smelly on a hot day with that many visitors going around. I couldn't get him to try the prisoner cage nor any of the other similarly demeaning attractions that people around were nevertheless rather happy to squeeze themselves in. He did watch them smiling though so I suppose they served their purpose anyway. And he got some sort of equipment more to his liking too so he posed with his new wooden axe as ferociously as a 6 year old in shorts and sandals and otherwise a sunny disposition can look:

Defender of the castle's gate (in summer garb).

Defender of the castle's gate (in summer garb).

As a bit of a break from rebuilded castles of all sorts, we tried on other days the tamed and less tamed nature all around Vilnius. For the town is indeed the greenest town of that size that I know - its parks are more like proper woods and at times, starting from the centre of the town it can easily feel that the town itself is a bit of outgrow on the outskirts of the woods rather than the woods being on the outskirts of the town4.

Tiny corner of landscaped gardens at the Belmontas park of many-closed cafes.

Tiny corner of landscaped gardens at Belmontas park of many-closed cafes.

Pretty mini-waterfall.

Pretty mini-waterfall.

Rather insensitive to green meadows and carefully constructed waterfalls, the child was nevertheless delighted to get to chase a ball with sunglasses and cap on just as well. So he chased the ball and played some football in recruited-company while we had a walk around and enjoyed the green and the quiet and the less crowded place.

The boy, the ball and the sunglasses too.

The boy, the ball and the sunglasses too.

And then we sampled the very tasty shashlik and I gave up on trying to find a drink I might actually like on their menu so I decided to get to know at least what I don't like, namely all the Lithuanian beers:

One beer among wasp-traps and other liquids.

One beer among wasp-traps and other liquids.

As they didn't bother to actually provide any sort of help naming them or labelling them, I had to match them to the menu as a sort of extra challenge to make the time pass while the shashlik was being done. But better than their actual names, I remember their very specific taste so that I can describe them like this: from left to right above you have some pish-wasser with an unidentified aftertaste; a glass of liquid smoke with no other taste; an almost-beer with a slightly bitter after-taste; the best Lithuanian beer that turned out to be Belgian, of course; a foamy yellow wasp-attractor liquid.

To forget about beers though, there were otherwise in other places more interesting drinks, from those for little ones...

The more drinks the wider the grin!

The more drinks the wider the grin!


...to those for very stubborn ones:
A very stubborn wine in various colours.

A very stubborn wine in various colours.


  1. The town has changed in many ways but most striking of them all are two that I can see: a lot of new buildings appeared; a lot of the local specific goods - including a whole selection of caviar in the shops! - all but disappeared. The change of wind from east to west is clear but nobody seems to have noticed that the problem stays the same - it's one of balance and strengths of the winds that are let through, not one of choosing sides. A hurricane from the east is just as bad as far as I can see as a hurricane from the west. Anyways, the locals are otherwise generally helpful and pleasant enough but you'll be able to hear some outbursts too - especially if you know what language to listen to, at what time - and otherwise there is the same boredom decay that I saw recently hanging over Romanian towns, almost palpable in the standard-malls, among the rather idle employees that have to watch rows of chained items such as school bags that cost 300 euros or more each, for no clear reason at all. 

  2. It was still there some ~10 years ago when I last walked the whole centre of the town and took in all the details, red bricks included. And I know now that I should have written it all up as it was then, for I'm now sorely lacking any way of providing the references that my mind throws in at almost every other sentence. But at that time I couldn't see anything worth writing about - I explored the city and took it in without any need to spit anything out again. Perhaps I was way too inwards focused, perhaps I was too young and too foolish to know better. But mostly I had had by then such a terrible and prolongued lack of anything useful coming from the *contemporary* outside that I maintained communications very close to a minimum really. 

  3. Until about 1410 when the Teutonic Knights were defeated. 

  4. This is true in a direct sense too: it's the only town I know of where you need to go *towards* the centre to get to the biggest parks rather than away from the centre. On the first visits this made a total mess of my internal bearings, of course. 

August 12, 2019

Camera Tests of a Sunday

Filed under: Lyf, Young, old and oldest — Diana Coman @ 3:49 p.m.

As I've finally retired my 14+ years old1 Sony camera and got myself the currently recommended still-Sony camera, I was rather curious if it does anything to my daily lack of photo-enthusiasm. So I started with a test on the nearest rose bush that I brought out from wilderness2 and into the light - for added photographic points, there were even a few water drops still on it (click for full-resolution, ~6MB with-droplets-image):

Water drops on a rosy-yellow opened rose with a bud nearby.

Water drops on a rosy-yellow opened rose with a bud nearby.

It certainly looks *better* than what the 14+ year old camera can currently obtain (though it used to do better) and it's certainly true that the new camera is lighter, smaller, with a bigger screen and the same sort of interface even, only improved - for once, actually improved! Such wonder. So I stalked a butterfly too but it didn't want to open up its wings while observed:

Brownish butterfly (perhaps a Small Heath aka Coenonympha pamphilus aka Pamfil?) on a garden bush.

Brownish butterfly (perhaps a Small Heath) on a garden bush.

While I was watching the rose and the butterfly, my child was watching me with a certain electronics-related interest since I had told him that he may indeed use all the new components but only as he gets to actually know them with the help of everything he has. So after a while, off we went to figure out just what do resistors do in a circuit and how to measure intensity or voltage and what a potentiometer might possibly be. As he had more work to do on the figuring out front really, I continued with my own camera testing:

Child making a series circuit to see the effect of different resistors.

Child making a series circuit to see the effect of different resistors.


What does this potentiometer do?

What does this potentiometer do?

And after quite a while of circuit-making and switch-switching and delighted laughter when things happened exactly as he thought they would (and surprised questions when they didn't), he remembered suddenly that there were still some remains of a certain walnut and cocoa Chec3 of very young age indeed. So I ran faster than him and managed to mess up a picture of sorts while there were still any pieces left on the plate:

Pieces of walnut and cocoa marbled cake on a green plate.

Pieces of walnut and cocoa marbled cake on a green plate.

Now that this camera is indeed all it was said to be and even something extra (I hadn't quite realised just how much smaller and handier it can possibly be), all that it's left is for me to put this take-photos-thing on the list of daily (or at least regular) requirements, huh. Though I still think the kid got the better toy this time...


  1. It's a usual lifespan, even on the young side really! 

  2. When we first moved to this house we've been told by a very-convinced woman that the garden is "very low maintenance, don't need to do anything really." Even at that time, it was enough to look at the garden and one could indeed see that she hadn't bothered - for years even - to do absolutely anything at all about the garden but that of course does *not* mean that nothing was *needed*! Still, she had no idea what I meant, of course, of course. She saw no need for anything and therefore nothing was needed - not as if this is not the usual excuse, isn't it? 

  3. Chec is a sort of easy-made marbled cake made in 1001 variations as the chef decides: in this incarnation I left out the rum and it contained crushed walnuts + the few brazil nuts and macadamia nuts that were lost among the walnuts; and cocoa in half the dough of course, as otherwise there'd be no marble effect. 

August 7, 2019

A Visit at the Recycling of War Artefacts Museum

Filed under: Lyf, Tgdyk tgdyk — Diana Coman @ 7:08 p.m.

His name was H. and he was made to fly. H. flew sometimes for fun, sometimes for duty and nobody really stopped to separate the two - how did it matter whether or when it was one or the other, anyway? After all, H. had made loops in the air when followed by the eyes of children waving flags but also when trying to avoid a quite different type of followers. In between flights though, there was also a lot of travel on land and on sea, chasing the next possibility to fly and getting in the process a lot of markings from all the travel and from all the chasing. But it was in the end a simple fire after taxying that kept Harrier ZD4611 down long enough for it to be declared the past and rather than repaired, just hung on ropes at the museum, in a bit of a mixed-up exhibition, next to a bomb of previous times:

A WW2 bomb next to a Harrier plane active from 1990 to 2010.

A WW2 bomb next to a Harrier plane active from 1990 to 2010.

We visited the Imperial War Museum in London (IWR) at the end of June this year but I never bothered to write down anything about it - it's a bit of a mix really with some interesting bits (there are Robert Capa's photos taken during the landing of American troops on the beach in Normandy on 6th June 1944; there are also regular events with WW2 veterans - at times and depending on your luck, you might get a glimpse of what they made of it), some reasonable parts (I hadn't seen the insides of a bomb before) and some terribly propagandistic stuff - at times the three are even mixed, what can you do. As I was clearing up my old camera today, the few pictures I took at the time (and promptly forgot about) came to light and so here's the entrance too, from the only awkward angle I could find at the time to avoid having some t-shirt clad icecream eater in the picture:

Barrels of 2 naval guns stranded on land in front of the former-hospital that is now the Imperial War Museum in London.

Barrels of 2 naval guns stranded on land in front of the former-hospital that is now the Imperial War Museum in London.

The entrance though is quite representative of the whole place - it makes me think more of recycling and propagandistic posing than of war itself (then again, everything is indeed forever recycled and arguably propaganda of one sort or another too). The building itself is a former hospital that recycled in the 19th century the Ionic for its columns. The two guns pointing away from it are barrels of naval guns taken from 2 different ships - the link being that both shot at least once during WW2. The shells are planted in neat rows for framing the picture I suppose and serve inevitably as climbing/sitting places for bored children. Mine liked at least the guns (they are BIG) but wasn't impressed by the shells (why are they yellow?). He liked the aeroplanes inside but that's be default currently - if it's an aeroplane, then and therefore it is interesting. And he listened politely to the old man telling his story of what it was like living as a child in London during the war, bombings and deaths and then evacuation and all. After which he raised his hand and waited his turn and asked of course about the one thing that was indeed most interesting from his point of view: *what* was inside this bomb exactly and *how* did it work?


  1. According to the Imperial War Museum docs, the plane is a vertical/short take-off and landing jet aircraft constructed in 1989, used in Iraq, Kosovo and Afghanistan and retired in 2010. 

August 6, 2019

The Widgeting Paws of Pointerism (Notes on Graphics in Eulora, V)

Filed under: Coding, Eulora — Diana Coman @ 5:02 p.m.

It took indeed more than a week and I'm rather surprised it didn't actually take even longer than two weeks to get *anything visible* out of it. It's all one strand like Stan's spittoon after all, so there's rarely just "one sip" that doesn't bring in the whole rot with it and I have to fight over and over the urge to just burn it all down and start a sane thing from scratch1. Nevertheless, a lot of deep breaths and assorted cussings later, here's a brief summary of the main achievements, in the order they were made:

  • some useless crap was removed and the whole thing made to work without (e.g. the doll with its dependence on a special sector in the map file);
  • the initial loading and "pre-caching" of meshes, textures, materials, maps and 2D stuff was excised (there are still the shaders remaining though as well as 1001 "preferences" in as many files in yet as many different places, sigh);
  • the actual handling of 2D icons and GUI images in general (e.g. buttons, borders, arrows, window decorations) aka the PAWS was dissected and exposed and roughly mapped as ugly as it is;
  • as recorded proof of breaking PAWS and because of its shameful lack of proper way to load images on actual demand, the whole thing has had a run with the stupidest "mouse pointer" available in there and otherwise with absolutely no 2D images at all for the very lulzy effect that it even looks better in some ways than with all of the various pieces of "art", here it is:
    That snot on the screen is the mouse pointer on the black background starting screen.

    That snot on the screen is the mouse pointer on the black background starting screen.

    PAWS's shame: the better-looking interface with no images whatsoever (clicking the invisible widgets still works!)

    PAWS's shame: the better-looking interface with no images whatsoever (clicking the invisible widgets still works!)

The path that led in the end to the above started with me looking - as initially planned - at how the character (as moving sprite) is handled or rather mishandled, consider: there is the CEL layer that supposedly provides on top of CS the sort of structures needed by games to store and manage the various entities and objects; PS however "uses" it in principle but in practice it still mainly does its own thing anyway (and by now I strongly suspect that this pattern is simply because nobody ever spends the time to understand what they use); specifically, the PS way is to have a pscelclient class that supposedly manages game entities on client side (shouldn't CEL have been enough for that, you ask? most probably yes but that'd have taken someone to figure out first exactly how it works and who has time for that!!); but then there is *also* a pscharapp class that handles the appearance of the character (apparently that's too low stuff for "management" to handle) and there is also a psclientchar that moves about equipped items because this is yet neither management nor appearance but absolutely something separate - though you'll be hard pressed to notice much separation in the code for all this theoretical separation; and to top it all, the inventory and doll views that precisely reflect character's appearance and equipped items are actually the domain of something else entirely - the PAWS; and the PAWS (which is supposedly so separate as to bother to be a plugin by itself) in fact messes about with pretty much anything and everything from the engine to shaders and textures and 2D images (which are still loaded as... textures, but those are textures-this not textures-that) and xml-defined maps and hardcoded paths to all sorts of files it expects - nay, demands - to be present and just-so and at-start but oh-so-configurable. At which point it became clear that the PAWS mess is indeed such a large part of the whole mess that I'll simply have to get to the bottom of it just in order to move further at all.

Looking at PAWS more closely revealed that it's meant to be a GUI system. This initially rather puzzled me because there IS in fact already another GUI system in there, one that PS uses/relies on as a dependency, namely CEGUI. Then again, the PS style is to "use" something by simply sitting on top of it and mushrooming a lot of managers with hardcoded paths and expectations that they know the whole possible world upfront so there should be no surprise at PAWS, which is precisely this sort of thing - it mushrooms widgets and pointers rather than something-else and pointers, that's about all the difference from all the other PS masterpieces.

Masterpiece aside, what IS this GUI system PAWS? As far as I can tell, it's a lot of widgets so well organised that there are no less than 3 methods "FindWidget" because the 1st one (defined in pawswidget) checks the current widget and its children only, the 2nd one (in pawsscript) checks also the parent of the current widget while yet the 3rd one (in pawsmanager because yes, of course there are all sorts of managers) simply delegates it all to "mainwidget" aka a sort of calling the 1st one from the top of the tree (but no, they couldn't possibly notice that it's meant to be a tree and there are well-known algorithms for searches in a tree). Anyways, the fun part with widgets is the way in which they are defined really as each widget has an .xml file (in data/gui) that supposedly defines appearance only (though more concretely it's about which elements it contains and on what position) and a .cpp file (in client/gui usually) that supposedly defines behaviour. The funny bit however is that both of those, for all their pretense of clear separation (they even are in totally different dirs, yes?), quite directly reference both one another's bits and pieces AND global, all-of-a-sudden-made-hardcoded parts: the appearance references by name other widgets (that it uses for specific roles and in specific places so it's not just a name really) and "resources" aka pre-loaded images; the behaviour code in turn has to reference various components of course. And in all this, apparently nobody noticed that before you can talk of behaviour and of appearance, there has to be somewhere a *structure and nature* of the thing that actually is the core and therefore the driver of everything else... Then again, what structure and nature and such silly notions, when the whole thing is bent on defining anything and everything by its current, temporary position or at best some role it might fulfill for a while2.

The widgeting PAWS further has all sorts of notions regarding appearances: there are "skins" and "styles" and "resources" and they are all both hardcoded and expected to be fully known upfront. The Great Paws knows not only all the world that is but also all the world that could possibly be (the world as it defines it is all nothing but labels anyway so it makes sense in a way). And it enforces this by whining and even wagging its finger at the user if it ever finds that a file with what it *knows* is the "right" name is missing from its expected place, quite literally giving orders to the user, as the message spit is this:

"ART ERROR: PawsTextureManager loaded the image %s which was missing from the imagelist.xml and was loaded on demand. Add the image there!"

I'll add to the above: and blow your nose and stand up straight and cut your nails shorter! Imagine that, being such a shitty user that the poor, poor PAWS had to actually load an image on demand (how degrading!!), you nasty user, you! And note that this "on demand" is anyway the sort of "you demand what I'm willing to do or no dice" not any sort of actual demand: it only means it deigned to look (because it had to use that image) in the *same place* it looked initially (when it tried to load everything that there should ever be) just because you are the sort of shit that failed to put the image there when it looked the first time, you know? What sort of user does such a thing to a poor piece of code, you tormenter, you, shame on you!!!

Before you get your hopes up that there is at least some sort of "loading on demand", bash those hopes one over the head: for one thing this "on demand" still relies on the predefined list of what there *can* ever be so that if you request a "resource" it doesn't know about than tough luck, it won't try to look for it, it's not that stupid to do something useful; for another thing, there is no way to actually call this on demand: it's just a way of doing rigidly the same thing but expecting a different result because meanwhile the world should have better come to its senses and fit the expectations already, what.

If the above sadness is not enough, add to it this significant bit: PAWS considers itself a plugin and as such entirely separated from the actual client and therefore unable to use whatever the rest of the client knows. Sure, in practice this separation "works" by means of the main client class simply passing pointers to PAWS on creation - why use CPP if not for pointerism, after all. Moreover, the added benefit of this separation is that PAWS also gets therefore to have its own set of repeated XML parsing of all sorts since it can't use the already-repeated XML parsing that the client anyway suffers from. And finally, it makes somehow perfect sense to "separate" the main client from the GUI system seeing how they both use the same graphics engine anyway and moreover the main client loads some images as textures while PAWS loads...well, some images as textures, yes. But they are not the same "class" of textures, so that's significant separation, see?

Besides deep red, I tell you what I further see: since I have no intention to pass even more pointers on or otherwise to force this "plugin" nonsense on everything just for the very specialness of PAWS, it's way more likely that the paws will be clipped more to size and therefore will take their place as yet another of the many classes inside the main client, possibly together with all the rest of very-special-plugins if need be (of course the dependencies are not that simple). I'm still pondering this, mainly because the idea is to touch as little as possible the code rather than as much as it takes to clean it (mainly because clean it won't be anyway). But one way or another, I will have to find some reasonable way to bring PAWS in line with the rest and have it go and load resources from wherever (and whenever) it is told to. This might even require more discussion in S.MG's boardroom but at the moment and as a result of all the adventure above, I have at least a much clearer idea as to what the 2D part is all about so there is therefore a point to even start the discussion from.


  1. While it might *seem* faster that way, it's not, nor does it really make sense if one calmly considers everything involved. Urges like this are simply focused on getting rid faster of the current set of problems and do not care nor stop one second to consider the alternative set of problems that are bought by such "solution". So yeah, urges make very poor guides, how surprising. 

  2. And no matter how much I try to *not* see it this way, it always is the case that the closer one gets to the "how things look" and therefore in this case to graphics, the more confusion and more monkeying there is. 

August 3, 2019

Silently Unhappened on TheOdinProject.com

Filed under: Dark Modern Ages, Outreach — Diana Coman @ 2:49 p.m.

From the series of "I must be doing something right if *they* are so afraid of me", I had today the lulz surprise of finding out that a derpy forum1 "unhappened" silently my account2. As in literally, vanished entirely not only my "page" but also what comments I left for others leading to the great achievement that now there are replies to my non-existing comments3. Wouldn't you say that's great for learning? You get for once a user who can and is willing to actually help others around and then you ...unhappen this user without a word even because... what exactly? No idea but possibly they have a bucketfull of "oh noez" that I kicked over without even trying or something4.

Oh noez and all that but imagine it - after making an account and engaging with some newcomers there for their benefit5, the loss on my side is... what exactly? That I will now totally set the bozo bit on this particular derpy forum? That they give me now an excellent antecedent as to why exactly it's a mistake to even take any notice of their "forum" interface and accounts and all that pretense at all? And that clearly from now on I'll document upfront each and every descent I still deign to make into such sad holes? Or perhaps that they are slowly but surely adding concrete fuel to my otherwise sluggish motivation for pillage and burning, that must totally be their gain I'm sure.


  1. Since can't derp without pretense, it's called theodinproject and I'm not going to link it, no. It has a stylised hunting trophy icon and is otherwise a sad trap for web-developer wannabe misguided souls. It runs on "Discourse" too so that it's in *that* bucket rather than in a different bucket (e.g. flarum, *BB and so on.) for all the difference that makes to the caught crabs within. 

  2. Here's what it says today at the link for my account, preserved in amber for the future: archive.is/FcGC6 

  3. Here's an example of a reply to one of my comments and I'll let you judge how terrible my comment must have been given the reply: "That's an excellent point - I did take some statistics/logic and reasoning courses as well, though, so hopefully that'll help with the literal-ness!" 

  4. By now it's probably extremely easy too as I'm clearly alien to them. 

  5. In fairness it was all of 20 minutes first-pass sort of thing, to get the pulse of the place - apparently it didn't even survive the lightest touch, who knew there are such wallflowers on the internets. 

Older Posts »

Theme and content by Diana Coman