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:
- Game World
- Concrete objects
- Terrain
- Water
- Air
- Characters
- Structures/Items1.
- Abstract objects
- Time
- Self
- Sector
- Concrete objects
- Representation
- Graphical
- 3D
- 2D
- Skin/GUI
- Audio
- Graphical
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:
- Files - relevant protocol messages 4.4 File Request and 4.3 File Transfer.
- 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:
- int8/uint8
- int16/uint16
- int32/uint32
- int64/uint64
- float (4 bytes)
- position (3 int16 as per protocol specification)
- rotation (3 int8 as per protocol specification)
- text (2 uint8 giving total size, followed by up to 1470 characters.
- rgb (3 uint8 standing for red, green and blue2 )
- rgba (4 uint8 storing red, green, blue, alpha)
- size2D (2 uint64 height,width)
- size3D (3 uint64 height, width, depth)
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 > :
-
Root > there is only ONE object of this type and that object has id "null"
- 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).
- Self_Info_ID : Self > id of the abstract object, not the id of the player's concrete character object.
- Current_Date_ID : Date > euloran date
- Current_Time_ID : Time > euloran time
- Client_Skin_ID : ModSkin > graphical user interface resources
-
Sector
-
CurrentNameID : Name
- Value (text): Final
- Terrain_ID : Terrain > the heightmap (+ material palette)
- Air_ID : Air > ambiental light and weather (?)
- (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.
- (Water_ID : Water)* > bodies of water
- (Character_ID : Character)* > anything that is active/can move;
- (Structure_ID : Structure/Item)* > anything that is passive/can't move and is not terrain/air/water/weather
-
CurrentNameID : Name
-
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)
- CurrentPlayer_ID : Character > player's actual character with data that everyone can access/see
-
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
-
Date_Of_Birth_ID : DOB
- Value (date) : Final
- Vitals_Profile_ID : VitalsProfile
- Skills_Profile_ID : SkillsProfile
- Inventory_ID : Inventory
- Equipment_ID : Equipment
-
Inventory
- (Item_ID : Structure/Item)*
-
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".
- (ItemID : Structure/Item)*
-
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 (?)
- Year_ID : Year
- Value (text) : Final > should those be numbers?
- Month_ID : Month
- Value (text) : Final > should those be numbers?
- Day_Of_Week_ID : DoW
- Value (text) : Final > should those be numbers?
- Year_ID : Year
-
Time
- Hour_ID : Hour
- Value (uint8) : Final
- Minute_ID : Minute
- Value (uint8) : Final
- Second_ID : Second
- Value (uint8) : Final
- Hour_ID : Hour
-
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)??
- (UI_Art_ID : UI_Image | UI_Spritesheet) *
-
UI_Image
-
(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
-
Size_2D_ID : Size
- Value (size2d) : Final
-
Transp_ID : Transparency
- Value (rgb) : Final
-
Alpha_ID : Alpha_Lvl
- Value (float) : Final
-
File_ID : Image > should all be .dds or .png or fixed format?
- Ref (text) : Final
-
(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?
- UI_Image_ID : UI_Image > for the sheet as a whole, it still has all the details
- (UI_Sprite)+
-
(Pos_ID : Position)? > for sprite sheets - position in parent image
- Value (position) : Final
-
(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
- (VitalID : Vital)*
- Name_ID : Name
- Value (text) : Final
- Current_Value_ID : CurrentValue
- Value (uint8) : Final > assuming that those are still given as % of max
- (Skill_Group_ID : SkillGroup)*
- NameID : Name
- Value (text): Final
- (Skill_ID : Skill)*
- Name_ID : Name
- Value (text): Final
- Rank_ID : Rank
- Value (uint64): Final
- Practice_ID : Practice
- Value (uint8) : Final
> assuming given as %
- Knowledge_ID : Knowledge
- Value (uint8) : Final
> assuming given as %
- Name_ID : Name
- Value (text): Final
- Sex_ID : Sex > is this given and in what form? is it known for anyone or just for self?
- Value (uint8): Final
- Position_ID : Pos
- Value (position): Final
- Rotation_ID : Rot
- Value (rotation): Final
- Model_3D_ID : ModCal3D
- (Model_2D_ID : Mod2D)? > 0 or 1
- (Model_Audio_ID : ModAudio)? > 0 or 1
- (Model_Effects_ID : ModEffects)? > 0 or 1
- Name_ID : Name
- Value (text): Final
- Stack_Count_ID : StackCount > this will just be 1 for houses / some cases.
- Value (uint64): Final
- Quality_ID : Quality > this may be called "durability" for eg tools or houses but it's same thing anyway.
- Value (uint64): Final
- Position_ID : Pos
- Value (position): Final
- (Model_3D_ID : ModCal3D)? > ONE of the models 3d/2d should be present in general
- (Model_2D_ID : Mod2D)? > 0 or 1
- (Model_Audio_ID : ModAudio)? > 0 or 1
- (Model_Effects_ID : ModEffects)? > 0 or 1
- NameID : Name
- Value (text): Final
- Position_ID : Pos
- Value (position): Final
- 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"
- Material_Map_ID : Materialmap
- Ref (text): Final
> filename, hence "Ref", currently "Island_alpha.png"
- (Material_ID : Material)* > material palette to use (eg sand, grass, stone)
- 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
- Weather_ID : Weather
> therefore "water" could simply be in principle an item/structure with the "water" texture applied - TO CHECK.
- Item_ID : Structure/Item
> 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. ?
- Particle_Syst_ID: Particle_System > if going this route, this is TBF
-
BB_Size_ID : BoundingBox > this is used for collision detection
- Value (size3d) : Final
-
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?
- (Animation_ID : ModAnim)* > a character may have any number of animations
- (Submesh_ID : ModMesh)* > parts/subparts of the model; NB: atm sockets is still not used/unclear!
-
Scale_ID : Scale > intended scale of the model, this is a transformation to apply before use
- Value (float) : Final
-
Translation_ID : Trans > pre-transform to apply, translation; same as for scale - could be standard and therefore spec not needed?
- Value (3xfloat): Final
-
Rotation_ID : Trans > pre-transform, rotation; same std issue as above.
- Value (4xfloat): Final > (x,y,z,angle)
-
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
-
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
-
Name_ID : Name > name is used as an id by CS... eg "walk", "run", "jump"
- Value (text) : Final
-
File_ID : File > this is a .caf file for now; should format be a deeper level?
- Ref (text) : Final
-
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?
- Vel_ID : Velocity
-
Time_ID : Interval > this is "interval for idle or override actions", in seconds
- Value (2xfloat): Final
-
Idle%_ID : Idle% > this is "probability (as %) of this action being the overriding action"
- Value (float) : Final
-
Base_ID : Base_Vel > speed of translation when animation is used on its own
- Value (float) : Final
-
MinVel_ID : Min_Vel
- Value (float) : Final
-
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
-
MeshFile_ID : MeshFile > format is .cmf ; should format be a lower level?
- Ref (text) : Final
-
Size_ID : Size > is this actually mandatory/needed here? Can't quite yet tell.
- Value (size3d) : Final
-
Name_ID : Name > name of this part of the model, eg "Head", "Neck", "Left_Arm"
- Value (text) : Final
- 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.
- 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.
-
(Vertice_ID : Vertex)* > one vertex as a minimum
- Value (position) : Final > this is given in model's own coordinate space
-
(Triangle_ID : Triangle)* > each triangle is given as (i1,i2,i3) where i1-3 are indices of the vertices given previously
- Value (3xuint64): Final
-
(Normal_ID : Normal)* > there should be one normal vector given for *each* vertex
- Value (3xfloat) : Final
-
(Colour_ID : RGBA)* > there should be the colour given for *each* vertex
- Value (4xfloat) : Final > this means r,g,b and alpha channel
-
(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
- 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)
-
Transparent_ID : rgb
- Value (3xfloat) : Final
-
Alpha_ID : Alpha > this is int in the current code, hm.
- Value (int8) : Final
-
Pos_ID : position
- Value (3xfloat) : Final
-
Size_ID : Size > height and width
- Value (2xint) : Final
-
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
- Texture_ID : Texture > CS works with materials (it wraps any plain texture into a material anyway)
- (Shader_ID : Shader)* > a material CAN have several shaders applied.
- (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.
> 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".
-
Name_ID : Name
- Value (text) : Final
-
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
-
Name_ID : Name
- Value (text) : Final
- ShaderTypeID : Name > ugh; those are again predefined CS stuff/available shader types...
-
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.
-
Name_ID : Name > NB: those names need to match what shaders (those xml files) know/expect, for anything to work...
- Value (text) : Final
-
Value_ID : Texture|Float|2xFloat|3xFloat > the value of the shader variable has one of those types
- Value : Final
-
Name_ID : Name
- Value (text) : Final
-
CentreID : Centre
- Value (3xfloat): Final
-
ColourID : rgb
- Value (3xfloat): Final
-
AttenuationID : Attenuation > "type" of attenuation (?)
- Value (uint8) : Final
-
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:
- 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.
- 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.
- 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.
- 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
- 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.
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) ↩
NB: CS uses floats, with 1,1,1 for white and 0,0,0 for black. ↩
Comments feed: RSS 2.0
it's worth keeping equipment separate from inventory as a sort of de-facto cache even though they're conceptually very similar, because equipment will enter into all sorts of calculations re char's capacity / abilities. I do agree that the difference between items and structures is entirely spurious.
The euloran date is more complex than commonly realised. To quote from teh design document... fuck, I don't have it on me here. Anyway, there's seven months with 24 days and twelve hours each iirc. Leaving aside how the date of birth is ~not necessarily known~ (ie will be known in cases of scions inheriting, but not in case of npcs etc), there's all sorts of data about characters the server knows but doesn't advertise (eg, their true HP/BP/etc, or their genetic code). So this'd be an important distinction I think, between communicable and secret attributes.
By the way, is "Air" where things such as particle effects go ?
> and sprite sheets won't be fine with filename as name for each sprite
How about hash of filename ?
> issues that are still unclear throughout
The one item seems to me that we want a packaging such that the tree is packet-balanced (meaning, it never answers with a succession of two packets that sum to less than a full packet -- we want to avoid chains of the type "what of object ?" "it has a color." "What color ?" "red" in favour of "what of ojbect" "it's color's red"). This should result from some fiddling of finals ; giving out spurious information is better than requiring multiple interrogation passes.
I'd kinda like sound. I know it can in fact be made to work because we tested this back in 2014 -- we even had some voice commissioned that worked out quite well. I'd also like a demonstration of modeffects, because it's not practical to have the gfx go without good particle effects -- afaik it should be capable to produce "snowglobes" ie bubble wherein it rains shiny confetti etc ; again this was tested cca 2014, to be deployed later.
Also, I'd mostly get rid of all the floats we can.
> it's worth keeping equipment separate from inventory
Ok, separate it will be.
> The euloran date...
I read from this: http://trilema.com/2013/eulora-game-mechanics-etc/
> important distinction I think, between communicable and secret attributes.
So far I made the distinction between Self (hidden attributes) and Other (directly visibly/known attributes). Is this enough? I can see the case where "Other" comes with some attributes that are optional (ie known for some but not for all) but I'm not sure if that will be enough. At any rate, I'd say this is not yet burning, possibly still premature to fully pin down.
> By the way, is "Air" where things such as particle effects go ?
Pending concrete practical experience and tests with it, yes, so far this is where I think it belongs.
There is a bit of tension/indecision here for particle effects that are in a sense attached to items really (eg sparks from a fire perhaps) but I'd still see them as parts of Air (and since Air is a property of the Sector, quite at top level really). Do you think they should better go somewhere else?
>How about hash of filename ?
It's not about length of the string or similar. A spritesheet is one single image (hence 1 filename and 1 hash, obv) that contains however several different images that are then specified literally by pixel position in the big image (the contained, smaller images are called sprites - confusingly and annoyingly because otherwise the term is also used for moving chars of some sort ffs). From what I gathered, it's commonly used for tiny images that are a set of sorts (eg all buttons and mouse pointers for a GUI skin). I suppose we could decide to just not use spritesheets and have 1 resource per file only but I don't really know just how much would that explode the number of resources and whether it's worth it.
> The one item seems to me that we want a packaging...
Noted for the next stages. So far I left packet-considerations entirely out, partially as I was anyway struggling to pin it down initially at all, grrr.
> I'd kinda like sound. I know it can in fact be made to work...
Then I'll have to look into this and see what is there. Fwiw though, while I'm sure that it *can* be made to work, I think it depends a lot on the machine setup (whether it works or not). The whole thing never worked on any of the machines I had it installed on (and it's been quite a few, with all sorts of HW & SW), from the start. I never really bothered to look at it (usually don't care about sound) but if it should be there, then it is added to the list.
> I'd also like a demonstration of modeffects
Ok.
> Also, I'd mostly get rid of all the floats we can.
Noted.
Overall, the very next steps then seem to be:
1. Particle systems (Air) and procedural textures (Water) loader/demo.
2. Modeffects def (should be mostly based on 1 but I'll look if there's anything more to it)
3. Sound investigation, loader/demo & ModSound def.
> I read from this:
A good, that's good law. Thanks goodness I published it, huh.
> Is this enough?
No. There's some attributes of the self that'll be shared and some kept ; and there's some attributes of others that are shared and some kept. For instance, I don't recall now where the new identification model was discussed on Trilema, but items will work according to what they're identified, but exist according to what they actuaslly are, permitting re-identification into something else. Thus the same object can be "Old Sword", "Sparkling Schimitar" and "Divine Schimitar of The Zodiac", depending who identified it and how well they did it.
> this is not yet burning
Not yet necessarily, but will be required before the thing can go live.
> Do you think they should better go somewhere else
I don't know right off. Conceivably, because should I want a horse to be followed by a trail of sparkles, how would this be managed if sparkles are toplevel objects ?
Note that I don't see the problem with all particle effects being proper first class abstractions, and thus you'd have to have the horse moving about as an object and the sparkle train following it around as an air effect, with a declared radius or w/e, so I'm not saying it's impossible.
Prolly good to have some tests, see if it's possible to have a NPC move on a drunk walk and be followed around by some kinda air effect.
> but I don't really know just how much would that explode the number of resources and whether it's worth it.
I'm kinda tempted to say it's worth it ; the "spritesheet" is a) leftover from ye olde days of 286 video games, when they did pre-allocated, video-buffer sized images and just cut through it by position (ie, it's a 1990s C-ism, resting on the C memory model / filth) and b) in any practical sense just extra machinery for no benefit, the spritesheet has to be cut upon delivery to be used.
> Overall, the very next steps then seem to be:
Works.
> There's some attributes of the self that'll be shared and some kept ..
This data hierarchy is entirely client-side, the way the *client* gets to see the world. As such, the secret (ie server-side only) attributes don't enter into it directly (hence why I didn't even mention them - I recall the discussion) - the only way in which I can see them matter here is to the extent that the attributes that *are* shared are consistent with what the reflection of not-shared should be (ie maybe there are some additional shared attributes to add to the hierarchy to capture the intended model since the above is mainly based on extracted minimal attributes from current ball of nonsense). Or is there something I'm missing here/not quite following?
> Note that I don't see the problem with all particle effects being proper first class abstractions, and thus you'd have to have the horse moving about as an object and the sparkle train following it around as an air effect...
This is precisely what I had in mind and how I see it working, yes.
> Prolly good to have some tests, see if it's possible to have a NPC move on a drunk walk and be followed around by some kinda air effect.
I'll add this to the list then.
> I'm kinda tempted to say it's worth it ;
I'm quite tempted to say the same, indeed but then again, I never quite saw the point of it anyway (precisely because... anyway cut, so wtf). I'll add it to the list to ban spreadsheets and use one image per file - if some actual problems with this really surface then, at least there will be something concrete to look at.
> Works.
Working on it then.
Ah yes, good point, this is client-only. I guess I got confused!
Alrighty, seems we're good here.
[...] the latest client data hierarchy draft revealed a gaping hole regarding the exact use and requirements of "effects", I've spent those past [...]
[...] fly, including icons, textures, materials, shaders, effects, terrain, lights, meshes, animations, everything! For the impatient reader, here's the update coming out of this only yesterday: diana_coman: [...]
[...] explored those past few days all the possible ways to get various aspects of air1 showing up in Eulora's client, I'm left with a working "air" element of sorts, a bunch of [...]
[...] that were already described in previous articles, including a first draft of a data hierarchy, its subsequent refinement and an initial brief discussion of how it works in [...]