Ossa Sepia

June 11, 2019

Eulora Client Hierarchy of Data Draft

Filed under: Eulora — Diana Coman @ 10:29 p.m.

This is a very first draft to help with the current work on enabling Eulora's GUI client to make use of new information as it becomes available from the server rather than expecting everything to be fully known upfront (as it currently does, laugh you not!).

Eulora's data is one big hierarchy with 3 main types of information: structure, description, representation.

  • 1. Structure (i.e. what entities are inside what other entities)
    Structure is always a tree of entities where each entity is given through ID (unsigned 32 bits) + Position (x,y,z,rx,ry,rz):

    The Root of the world will ALWAYS contain:

    • an *abstract object* with meta-info:
      • ID of "self" (SelfID)
      • ID of current location (aka "sector" or room or world or whatever else it is) (LocID)
      • List of Skills: list of (skillID, skillName, skillCategory, skillRank, skillXP, skillKnowledge) (?)
      • Game Date and Time (?) --- is this a meta-matter or is it a location-property?
    • the *top-most ID* (aka topmost entity); NB: this is not always the same as LocID since character may move into a location inside another location, presumably.
    • from top-most ID down, EACH node will have zero or more contained entities (hence, child nodes given through their unique ID and concrete position within their parent).
    • NB: each node can also have in addition to its structure-children (hence entities), any relevant number of description-children (see 2 below) or representation-children (see 3 below).

    • 2. Description of what entities themselves "are" through their relevant properties

      ANY structure-node may further have, alongside its children, one or several of the following properties (given as a tuple property,value):

      • name
      • description (??)
      • (- equipment slots (list of (slotID, entityID) ?) -- are those any different from "contained"? I can't see a truly significant difference.)
      • stack count
      • quality
      • HP (hitpoints)
      • BP (bloodpoints)
      • SP (stamina points)
      • MP (mana points)
      • SpP (spirit points)
      • MSP (mana spirit points)
      • weight
      • bulk
      • weight limit (max weight)
      • bulk limit (max bulk)
    • 3. Available representation of entities (graphics, sounds, effects, maps etc)

      NB: in principle there can easily be a structure + properties split at this level too since a graphical representation may have its own structure (e.g. map defined as a hierarchy of contained terrain + geometry meshes that have in turn different submeshes with corresponding textures/materials). This seems rather unseemly though and it's unclear if there really is a need for a hierarchy of graphical detail that is anything OTHER than hierarchy of world entities to start with. So perhaps this can be flattened so that representation of entities means just that: a list of relevant graphical characteristics of ONE entity.

      ANY structure node may further have, alongside its entity-children and its properties, one or several of the following representations:

      • Mod2D (aka 2D model; at its most basic, the filename of icon to show for this; tbd)
      • Mod3D (aka 3D model; at its most basic, spec for mesh including material/texture and sockets if any; tbd) ; NB: sockets allow graphical representation of contained (specifically "equipped" or "component") entities and therefore they should probably be identified by "position" so that the entity "child" on that position will then give the actual representation shown to the user (?).
      • ModAnimations tbd
      • ModMap (aka map for this entity; at its most basic heightmap + size (or is this fixed?); possibly also a list of materials to use + corresponding density)
      • ModWeather (unclear yet if this is any different from sounds+effects really)
      • ModSounds tbd
      • ModEffects tbd (unclear yet if this is substantially different from animations+sounds)
      • ModSkin tbd (stuff like window borders and button colours)

      ANYWAY: GUI may request whatever it wants from local cache, regardless of cache's own internal representation (just as cache may store data in any form, regardless of smg's own description of hierarchy).

    TO DO: flesh out in more detail each possible representation, for GUI to ask & work with + get it to actually work outside of/inside the intricate mess of ps paws, widgets, managers and whatnots maggots.

May 27, 2019

Eulora's Client Core: The Dedicated Requester

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

A crucial requirement of Eulora's new client is to actively request from the server ANY data that it may find itself missing at any point in time. At first glance, this seemed to me simply a matter of providing request services1 from Eulora's new Ada-based core and then adjusting the existing C/CPP code of the legacy client to make use of those services. This rather optimistic idea is of course plain wrong: "adjusting the existing C/CPP code" in this context is similar to saying that one "adjusts" a sheep to use the library - while it can certainly be done for various definitions of "done" and the sheep may indeed use the library one way or another, it's at best a huge waste (of time, of resources, even possibly of steak) for everyone involved and no matter how one looks at it.

Even leaving aside for a moment the trouble with "adjusting" the legacy tangle in any direction, the more important issue here is that this requirement is not as much a functional requirement as a non-functional, quality of service requirement: whichever part of the client provides data services, it should better be dedicated to the task and do whatever it takes to get it done instead of "providing" it only fair-weather style - if it's easy, there you are and if it's not easy then it's your problem really. In other words and in marked contrast to the very democratic "best"-effort-you-can-do-anything-anytime existing C/CPP code2, the new code should have a clearly defined task and then either complete it or die trying over and over again, taking full responsibility for the process involved, not just for some specific detail conveniently chosen nor - as an excuse for not delivering - for the outcomes that are not fully under its control3.

Considering therefore "active and dedicated request" as a quality of data service on Eulora's client side, it follows that its place is rather close to the data cache mentioned previously and at any rate inside the new Client Core since it's certainly not some additional part of client logic nor some bit of user interface. However, I'm reluctant to make it the responsibility of the cache itself since the cache is a passive structure that focuses on *storing* data and *providing access* to it. Mixing passive data storage with active data acquisition doesn't make much sense to me and even seems ill-advised for Eulora's client given the competing requirements: on one hand passive, immediate-response local data storage and on the other hand active, possibly-delayed and world-facing (i.e. communicating with the server) data acquisition. So I'd rather avoid this passive-active construction and have instead the two as separate entities: a EuCache dedicated to storing and retrieving on demand *any* data; a Requester dedicated to acquiring *any* data that is demanded of it. Note that the definition of "acquiring" here has nothing to do with the means through which the Requester actually gets this data (specifically nothing to do with the exact messages sent/received/exchanged with the server). Acquiring some data means simply that the required piece of data becomes available in the local cache aka EuCache. So the Requester will keep requesting this data from the server through whatever means it knows until either the data arrives and becomes available from EuCache or otherwise the whole client kills itself for lack of server4 and therefore of any possibility of playing the game.

Specifically, the Requester will be implemented in EuCore (and therefore in Ada) as a protected object exposing only a few procedures that are essentially notifications: some are notifications of demands for some specific piece of data (either an Object or a File really since those are the only 2 overall types of game-data that one can request from the server); the others are notifications of data being received or of timeout interval having elapsed (in other words a notification of failure to receive data). Note that the demand for an "Object" effectively means a demand of its properties and those might be indeed anything at all but each and every one of them will be either directly a value or otherwise an ID of another Object or of a File. All notifications (including those demanding data) are always accepted by the Requester but not necessarily immediately acted upon. Clients of the Requester do NOT control the actual requests to the server or messages exchanged and are not even concerned with those at all - the production of actual requests, their content and their timing are entirely the job of the Requester and under its sole control. Implementation-wise, the Requester will simply keep queues of requested Objects/Files and will then proceed as soon as it can to pack a request for as many of them as possible; this request will then be posted to the server and the Requester will set a timer to the timeout value so that in the worst case it is at least notified that nothing happened; when/if any data is received or when this timer expires, the Requester will check in EuCache to see what items (if any) of those requested are now available; any items that have become available will be discarded from the watchlist of the Requester (i.e. the demands for them are considered completed) and a new request may be created and posted to the server for any items that are still in demand but not yet available. Note that even in the event of a timeout, a "repeated" request to the server may not be identical to the previous request since the list of demanded data possibly changed in the interval.

One potentially iffy point for the Requester is its need to be notified of any incoming data. At the moment I don't see any real way around this, short of making the Requester poll at set times the EuCache and checking if any data of interest has meanwhile arrived. I don't really like this polling approach here because it's rather wasteful without good reason: any incoming data is indeed received and processed by another unit that is also on the same level with the Requester, namely the Consumer (the part that processes messages from the inbound queue). So the Consumer will have to notify the Requester when new data is received. While several Consumers may be active at the same time (at least one for Serpent and one for RSA messages) this is not a problem at all since the Requester is anyway a protected object i.e. thread-safe. Note also that even if (some of) the consumers fail to notify the Requester of some incoming data, the whole thing will still work if only slower than it could: the timeout timer will wake up the Requester and the check of data will happen there at any rate. In other words, the Requester is capable of reacting to events if notified of them but not dependent on those notifications to do its job correctly.

Given its rather complex task, the Requester is currently on the top conceptual layer of EuCore, making use of quite a lot of other units from lower levels. Currently, the main relevant units on this top level are the following:

  • Data Cache aka EuCache - this is a passive, thread-safe entity responsible for storing all and any data given to it and retrieve or delete it on demand. As such, it *owns* the specific format in which data is stored5 and it simply exposes functions and procedures for storing, retrieving, deleting and checking for data.
  • Communication Link aka Comm_Link - this is a passive, thread-safe entity responsible for persistent storage and updating of communication details, most notably RSA and Serpent keys for inbound and outbound communications as well as a message counter. This is effectively a specialized cache - where EuCache is for game data, Comm_Link is for communication protocol data. The requirements (including use contexts) and specifics of the two seem to me sufficiently different to keep them separate at least for now.
  • Consumers of incoming messages (RSA and Serpent) - those are separate, active tasks, responsible for processing incoming messages. Consumers own and get to define what "processing" means exactly but their role is to extract the data contained in the messages received and make it available for use by Eulora's client. In practice this means currently that Consumers will pass any data received on to EuCache for storage and will notify the Requester of any data receipt.
  • Requester - this is an active, thread-safe entity responsible for acquiring data that is in demand. It owns the process of data acquisition from the server and it accepts any demands of data specified by some identifier. While it guarantees that all demands will be served at some point in time as long as the whole program is running, it does not (and can not) guarantee when or if the corresponding data becomes available. It can't even guarantee that there IS any corresponding data and so ALL it can do is to guarantee that it will try with the same dedication for each and every bit of data to acquire it. Anyone demanding data can of course pester the Requester with more demands or give up or decide for themselves for how long they can or will wait.

And now that the main idea and overall design of this whole thing is at least quite clear to me, there remains of course the small bit of actually implementing it in full (rather than the current skeleton I already made) and sorting out the various implementation-level troubles that will appear as they always do, in all sorts of details. Relatively easy work compared to what follows it inevitably, namely teaching that C/CPP sheep to use the EuCore library...

  1. Mainly picking, packing and encrypting everything in the right format + sending it through to the correct place. 

  2. Seriously, think of it: existing client code is this event-driven thing where *anyone* can subscribe to any event and then "do" anything at any time provided of course that the any and anything are in fact very narrowly defined and set in stone even to the level of names of various art files (it has to be a zoneinfo.xml inside this and that and put exactly there, sort of thing). If this narrowing of "do" was not a price high enough to pay for such code "liberty", there is also the added reality of a huge tangle that does precious little indeed since everyone ends up calling anything from anywhere and no piece of code is really and truly responsible for anything bigger than a few variables here and there. And at the end of the day how could any code even be responsible for anything since it can't *own* any process by itself (shared! event-driven!) and it has to be passive, mainly reacting to some events or at most... signalling through events of its own but never able to rely on anyone giving a fig about its signalling! So there it is, code - like anything you do - is more of a mirror than you might think. And "teaching people to code" has way more layers than "teach them Java" and certainly more issues than current "courses" even seem to be able to imagine. 

  3. And now that it's clearly stated like this, tell me first just how many people you know who actually handle their own work like that? And just what bit of "programming language" you think one needs to teach so that you get programmers to actually design their code this way? 

  4. This "lack of server" is defined in practice as a number of successive timeouts on requests sent to the server, where the specific threshold value is chosen by the user via a config file. 

  5. Currently game objects are stored in memory in Hashmaps aka associative arrays while art/files are stored directly on disk. Note however that any of this can be changed without touching anything outside EuCache as it's nobody else's business. 

May 4, 2019

Eulora's Client Core - Basic Docs

Filed under: Coding, Eulora — Diana Coman @ 8:56 p.m.

As I'm doing anyway the work required for a saner Eulora client, I'm stuck as well with writing a minimal documentation for it, since on one hand there's no one else who can quite write it anyway and on the other hand there is no such thing at all1 for the old piece of inherited gnarl so the slate is blank, the space infinite and the need impossible to know in advance. So I'll just jot it down here for future reference and if you have anything to say about it, the sooner you write it down in the comments section below the better for you.

As general structure, the current plan for the new client is to have essentially 2 main parts: one is the actual Core, written in Ada and - hopefully2 - provided as a standalone library, blissfully unaware of ANY of the C/CPP legacy tangle; the other is an updated version of the current C/CPP tangle of a "client" that will use the Core for pretty much everything except the actual GUI. The GUI remains provided via CrystalSpace and cal3d, as it currently is. In other words, the Core offers an implementation of a basic Euloran client, to be used from/by any UI, graphical or otherwise as you care to make for yourself. Note that the interface is NOT the only thing you can build on top of the client Core. Essentially any client logic, bots and anything of the kind would still be the sort of thing built on top of / around the Core. A quick diagram of the whole thing looks like this:

The Core itself is currently made of 3 conceptual layers, in order from bottom to top: encryption utilities (EuCrypt), SMG communications (SMG_Comms), client data cache. The encryption utilities are those of EuCrypt: CRC32 calculation, Serpent encryption/decryption, Keccak encryption/decryption, RNG interface using Fuckgoats, RSA key generation, RSA encryption/decryption using TMSR OAEP schema. The SMG communication part provides mainly: UDP with fixed-size but configurable payload, in/out message queues and attached "consumer" tasks, config file reader, packing/unpacking (i.e. raw, bottom-most layer of SMG communication protocol), read/write of messages conforming to SMG communication protocol specification, thin layer on top for encapsulating a "communication link" i.e. required addresses, ports and keys for both ends. The client data cache keeps effectively the whole world of Eulora as the client knows it at some specific time and provides thread-safe getters and setters for anything and everything that it can possibly hold.

Note that the client's knowledge of the world is by definition a cache as it flows always from the server and entirely in response to client's own requests - there is by design no "push" of information or anything else from server to client at any time. So the client may request from the server anything and everything it wants to3, having however to decide for itself what to make of the answers it receives and even what "obsolete" means in various contexts. At the moment this cache is still in the works and for this reason the least fully-fledged but at any rate, it has to grow around the structuring of data that is discussed in the SMG protocol specification: a potentially infinite hierarchical structure of "objects"4 having each a subset of an overall set of potential "properties"5 with their corresponding "values"6. Due to this trinity of objects-properties-values with its corresponding trinity of ID spaces, I took to calling the whole thing a tricache but the name as the design are still in the works so they'll have to enjoy their own detailed description at a later date. Until then, what have *you* been working on and how is that going?

  1. Perhaps you count this spaghetti piece as documentation but even so, just note who extracted it in the first place, anyway. 

  2. I'm holding quite tightly to this idea as I certainly do NOT want to have it depend on any of the current C/CPP mess. This being said, I can't know in advance what I might still uncover so for now and until it's all done, the qualifier remains "hopefully" rather than surely. 

  3. This in practice is of course quite severely restricted by what it *knows*, unsurprisingly. 

  4. Where "world", "map", "actor" or "pot" are equally objects and not even the only objects. Essentially an object is anything that is present in the game's world. 

  5. A property is a pre-defined and public structure that specifies the *type* of values that make up the property and their actual meaning. 

  6. The values may be given directly (e.g. "3" or "somename") or by reference aka as an ID. This ID may be itself either the ID of a suitable object or the ID of a value that is essentially too big to pass around every time - in the protocol's specification this sort of ID is currently called for historical reasons "filename" but it's worth noting that there is no imposition for it to be stored as a file at any point. 

March 3, 2019

Inconsiderate Considerations or a Tiny Euloran Dataset on Blueprints

Filed under: Eulora — Diana Coman @ 8:57 p.m.

Blueprints in Eulora are currently the product of expensive clicks: millions go in to pay only for the most inconsequential of tokens, thousands come out and few of the blueprints obtained are what one wanted to get anyway. In typical euloran fashion however, this exercise in the frustrations swamps is anyway on one hand unavoidable and on the other hand potentially, eventually, greatly rewarding1 - with a bit or a bit more of luck and other assorted arcana. That being so, I let my luck do whatever it does and otherwise I set about to collect in one place a tiny bit of data on what comes out of where. About 200mn ECu later, here's what I've got when clicking them with a noob2:

Consideration Type3 Consideration q4 Bundle q Output q Blueprints obtained5
10 x Apprentice Tinker Considerations 179 37006 34 LTF, Slag, CT, CC, PPB, IO, DUH, SCS, BCT
10 x Apprentice McGuyver Considerations 47 32877 17 QF, POC, Rockpile, CSW, GT, PC, CB, CDS, ETD, RH
7 x Neophyte Gumbo Considerations 152 7528 14 NP, TT, FT, TF, WOA, BBB, ACG, BNG, CP, CF
10 x Neophyte McGuyver Considerations 2670 18389 91 SFH, IT, PS, MK, TM, BH, RH, CB, POC, HG

Conspicuously missing from the above, the very blueprint that I really wanted to see, namely BMS10. The BMS would be in the McGuyver line but 10 Neophyte clicks and 10 Apprentice clicks failed to produce even 1 single bp. Rather sadly, the Apprentice McGuyver clicks still produced the useless Caveman Bedroll blueprints and other such shit (Reed Hauberk!) that one has too much of, even just from Neophyte clicks anyway. It's totally unclear why exactly would some blueprints be SO common even though they are not necessarily the cheapest ones: take for instance the ton of LTF (4070 bv) or CT (1404 bv) blueprints obtained (0.1mn of each) and compare that with the 13 total BCT (540 bv) blueprints! If anything, it would be the cheaper blueprints that are harder to get but then again, I got tons of "Somewhat Fashionable Hat" and "Hoof Gloves" useless blueprints from the McGuyver line and those are the cheapest in that line (656 bv and 622 bv respectively).

Assuming that those rare bps aren't simply unobtainable at this moment for whatever reason, the obvious conclusion is that those considerations are rather inconsiderate of the ~200mn base value sunk into them and won't reveal in return even the very basic of *what* blueprints should one expect from where. Then again, it's not *consideration* you want from a good game, is it?

  1. Different players might find different things rewarding but a basic reward would be the rare serious "popping" i.e. obtaining for once millions out of thousands rather than the other way around.  

  2. the ~only way I have to actually get a wider spectrum of bps since clicks with Foxy end up high quality output and 1 type of bp in the usual cases; in the rare case, Foxy can in principle get more bps too but here I wanted to see precisely WHAT bps one gets from where so I suppose it's a gamble on the types more than the overall value itself. 

  3. Each crafting line in Eulora has its own Considerations line. Each line has several levels of which so far there are three seen: neophyte, apprentice and journeyman. 

  4. Quality of the Consideration blueprint used for this click. 

  5. They are ordered based on quantity obtained, from high to low. 

  6. ~=6.8mn base value. 

  7. ~=6.05mn base value 

  8. ~=1mn 

  9. ~=2.83mn base value 

  10. In the missing and becoming ever so rare range there would also be the CFT bp from Tinkering but at least I did not do a Neophyte Tinkering click this time... 

June 26, 2018

Eulora's Own CR50

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

Possibly similar to the CR50 item Stanislav has been torturing recently, a green "Microchip" of unknown internals and dubious usefulness has finally been teased out of the reluctant and downright hostile Euloran soil. It took only a bit more than 3 years of pounding said soil.

On the plus side, it seems to be quite valuable at somewhere around 110`000 ECu (aka 11`000 satoshi atm) base value. On the more usual *other* side, there is no known use for it at the moment1 and it came out very low quality too, not to mention potentially booby trapped for all one knows:

Eulora's own CR50! Microchip!!1

The floating Microchips!

At any rate, I hereby dedicate this very first lot of Microchips to Stanislav Datskovskiy. May all his quests be successful and take considerably less than it took me to find this item!

  1. It wasn't needed until now, which is of course "no indication of future performance". 

June 10, 2018

Chasing the Elusive Euloran Quality

Filed under: Eulora — Diana Coman @ 3:45 p.m.

Quality of items in Eulora is a big thing - it brings in more money for whoever can deliver it and it also gives one better dings. Or at least better chances at better dings1, it would seem. Welcome to the murky shores of Eulora, this land open to all and totally opaque to most2.

The most recent update3 was cheered for finally making it possible to actually do expensive stuff in a few minutes as opposed to a few months. After which there was silence and renewed confusion as to what is what and how much any darned thing is worth. Quite a lot of discussion ensued in the #eulora irc chan although mainly between me and Mircea Popescu as the rest of the veteran players4 seem to either have no clue or have no appetite for talking at this stage. Hopefully they'll find one if not both at some later point before totally sinking out of sight, unknown and unmissed for lack of actually being there, who knows.

While discussions in logs are all fine and good, they tend to be difficult to find and retrieve at a later time. So for my own future needs and potentially for others' use, I'd rather jot down here a few data points on all this. The most recent problem is that apparently *everything* works now as a quality sink: mining eats up crafted items of 4k quality to give back harvestables at 900q while crafting wants also to eat harvestables at 900q to possibly give something back at all (not even clear if >900q, at that; a reported craft that "almost works" brings down q from 90 to 84). After all sorts of experiments with my team of noob and not-so-noob helpers, I suggested that people might simply be approaching the issue here from the wrong end, a sort of trying to dig their way out of the hole instead of making a ladder to climb back up. I know that a big-enough dig can indeed get one out of any hole through the other side, but Eulora's rather short on shovels at this very moment5. So how about that ladder then? It starts with more experimenting and concrete data, such as this, collected over only a few crafting runs of Slag (base value 677):


Tinkering Rank Sortage Rank Blueprint Quality Bundle Quality Output
1265 448 133 664 0 Slag + TPF q401
1265 448 67 664 0 Slag + TPF q285
1265 448 1 664 4-5 Slag + TPF q32
245 77 133 664 2 Slag q213 +TPF
245 77 67 664 3 Slag q151 + TPF
74 67 133 664 2 Slag q198 + TPF
74 67 67 664 4 Slag q141 + TPF

All the runs had remarkably similar results (same quality always, same number of slag items always except where it appears in table as 4-5 i.e. sometimes 4, sometimes 5) so I simply recorded one result for each combination. The bundles there are all identical and made by the highest skilled crafter as she can pack most value into the bundle. Specifically, each bundle is made out of 17 Flotsam q192 and 11 Shiny Rock 187q. For one thing, this suggests that the highest crafter packs the ingredients for almost 4 slags into one single bundle. For the other, it means that any output < 190q is anyway a sink of quality, no matter how one looks at it. And looking at it, there is some support on both points: 4 slags are reliably obtained by highest skilled crafter with a blueprint of lowest quality possible, 1. They are however q32 meaning that quality was severely lost in the process. When quality is not lost by the highest skilled crafter, it is however totally transfered to numina it would seem: all output is numina and no slag at all.

Considering the results of the other two crafters, the most interesting part is that they can actually get Slag of higher quality than the inputs that went in: for the same ~q190 harvestables used as input, they get reliably outputs >q150, even close to q200 in one combination! So for one thing it's certainly NOT true that crafting is a sink of quality, quite on the contrary: it clearly creates quality of output - the only trouble is however to match the sort of output one wants (i.e. product not so much numina at the moment).

The even more interesting bit suggested by this teeny tiny amount of data is with respect to just how much of the actual value going in is then obtained back as Slag rather than numina. The input value is roughly 677*6.64 = 4495 ignoring the value of the blueprint (which is not much at 67*1.33 maximum in there). Highly skilled crafter gets precisely 0 in Slag out of this and all of it in numina unless they go for low quality when they get between 4*677*0.32=866 and 5*677*0.32=1083 so anyway about a quarter maximum. By contrast, middle level crafter gets 2*677*2.13=2884 or 3*677*1.51=3066 at lower quality so about 70% of the input value. And lower level crafter gets even more at their lower quality 4*677*1.41=3818 (or 2*677*1.98=2680 for their higher quality).

Before jumping to any conclusions, I'll add that I'm quite sure that the data captured there (i.e. Tinkering and Sortage skill ranks, blueprint quality, bundle quality, item) is quite unlikely to really capture ALL factors that influence the outcome. For one thing I can tell for instance from long experience with those characters involved that the highest skilled crafter tends to be rather unlucky in everything she does, while the middle skilled crafter tends to be quite the opposite - lucky and then some more.

With the above caveats in mind and other potential limitations quite obvious6, a conclusion is to be drawn and that is that at least on such low base value items beginner and middle level crafters are actually in a very good position to bump up quality and make a killing - if only they do buy the bundles of a highly skilled crafter! In turn, their output is likely to actually help highly skilled crafters as it gives them more quality as input for more valuable crafts presumably.

As for the highly skilled crafter, it would seem to me that she would really need to somehow pack in at least 4 times the value of Slag at her output quality of 401 in order to stand a chance of getting q401 Slag. That means she needs a bundle of 4*677*4.01=10859 so about 3 times more than what she made for this little experiment. Either she gets that from an even higher crafter (who can pack more of same q harvestables into one bundle) or she uses harvestables at quality at least 600 by the looks of it. Good luck with that my lovely, as q600 harvestables will come at a hefty premium at least from my wares - if they even come at all as it's not all that clear at this moment that such stocks can be replenished if used!

Other than that: isn't it marvelous how much one can get even from only a few numbers? If only they do bother to get those numbers in the first place, of course...

  1. The term of art in Eulora is "pop" as in "1002mn pop, wow!" i.e. you put in 10mn and got 1002mn out of it, you lucky bastard. 

  2. That post was written in 2015, yes. Not much changed since then in terms of players' understanding of Eulora's actual workings it would seem. Poor Eulora, so totally incomprehensible, so entirely misunderstood... 

  3. 'Tis not even by far the only update Eulora went through so far. And all updates introduce changes that so far seem to mess up players' previous plans something fierce. 

  4. Noobs have yet some other things to figure out before standing much chance with this really. 

  5. And since I'm not that young anymore in Eulora either, I can tell you that I've subsidized this sort of approach at least once before and I don't want to do it again, ever. It was costly, very very costly. 

  6. Very small sample is the most obvious but you really are better off thinking for yourself on this. 

June 5, 2018

The Lack of Dust - A Very Euloran Problem

Filed under: Eulora — Diana Coman @ 6:23 p.m.

Collected Dusts in Eulora are a thing - a very useful and currently very much required thing. Consequently, according to the usual Euloran workings, Collected Dusts are also... rather sorely needed and totally missing from the market. In other words, Collected Dusts are hard to get, needed by the ton, while also unknown as to actual value - the usual stuff. And so Foxy set up to... get those1, since she is anyway best at Lapidary2.

At first, the recent update seemed as if it might help for once - first level numina such as Dusts are normally obtained as a byproduct of crafting in the respective line. That would mean that one gets tons of Dusts simply by clicking something in the Bouquinism line. And that is... true of sorts but the trouble is that Bouquinism is a bit special and most of its items give stuff-other-than-numina (blueprints mostly). Moreover, while the recent update seems to have turned skilled crafters' clicks into mainly-numina-producing clicks, this does not really hold for Bouquinism! Click on Maculature and instead of loads of Dusts, one still gets loads of... Little Bits O' Nothing. What do?

Well, whenever the rule doesn't work, one needs to find... the exception, of course. For various definitions of find that might involve workarounds and workthroughs and workaboves and workbeyonds and workinbetweens - more generally speaking: WORK. So work it is then, onwards! In this case the work is mainly to figure out how to make mites in large quantities through lots of smaller clicks since apparently I don't have enough input stuff to get more than a few mites through huge-quality single click sort of thing.

First, I tried all sorts of combination-clicking on Maculature in the vain hope that Bouquinism might still sort-of-work like the rest and spit some Dusts: high q bundle with total noob -> ton of LBN (Little Bits O' Nothing) and nothing else; high q bundle with high q bp (recipe) and Foxy's click -> ton of Nothing just the same; you name it, I tried it -> no, nope and nono.

Second, I made then some Bird's Nest and Gin, poured it over that WPL3 that nobody wanted yesterday but wanted today4. That made the ECV5 in tiny quantities and ...DUSTS! In... some quantities because on one hand I did get a few thousands of them but on the other hand Foxy needs at least 3300 for one single Lapidary click that makes usually only about 20-30 Mites so by this measure... still totally and utterly stuck (and no, making some million of Bird's Nest and Gin is not a useful "solution"). What do?

Third, I got a total noob to look at Foxy's Toil recipes (the ones that make Mites out of Dusts). And what do you know? Noob can make a bundle with one single Dust and one single WOA (Water of Anamnesia - another thing that seems to be rather wanted and in short supply at the moment). So noob was set with the bundling bot to make a few hundred bundles that came out an actually reasonable ~1300 quality because Foxy's Dusts are high quality and Foxy's ancient WOA are ALSO high quality. Wonderful, except for a teeny tiny problem: clicking a 1300 quality bundle with a high quality Toil bp seems to end up for Foxy in... no Mites, only Gem Dusts (Lapidary numina). On the other hand, clicking it with the noob gets Mites, but poor, sickly and stinky ones - frightfully low quality, not to mention basically wasting all that Lapidary experience on the unsuspecting noob. Once again: WHAT do?

Fourth, got the big mixing guns out of Foxybot: blueprint quality doesn't have to be huge if one also has6 quality 1 blueprints of the same type! Some many clicks and 2000 mixings later, there we go, found some sort of combination that works! Foxy reliably gets at least 10 mites per click - not to mention many more when she pops or mini-pops - at a quality above 500 and she has *hundreds* of bundles and blueprints to click right now!

And the cherry on the above delightful cake is that it takes only 2 of those clicks for Foxy to rank up in Lapidary. Combined with the bot's powerful crafting-with-bundle7, she basically got 100 ranks up in one hour today and scooped up the book-prize for being first to reach 600 rank in Lapidary!

Onwards and upwards, let's reach that 800 Lapidary before tomorrow's update 'cause I'll be busy mining: there are new problems to solve, troubles to find and generally millions of coins waiting to be picked up, scooped out, teased away from Eulora! If only, of course... you actually work at knowing how to do such a feat. Do you?

  1. By now I can say I have a thing for... prickly problems let's call them, what can I do. 

  2. The crafting line that works on numina such as Dusts, transforming it from lower levels to higher levels (e.g. from Dusts to Mites and so on). 

  3. Worthless Putrid Leather 

  4. Ha, HA! 

  5. Extremely Creaky Vellum 

  6. by means of previous noob-clicking, at another time, there's nothing totally useless if only done correctly in Eulora, you know? 

  7. No, you don't have this working anymore? Awww. The help and the code have been there for ages, waiting for... you . Where have you been? 

May 24, 2018

A Tiny Stab at a Little Pricing Problem

Filed under: Eulora — Diana Coman @ 10:57 p.m.

To start off, here's Foxy making disgusting goop in large quantities1:

Why is she making that? Well, for profit, what else. With each click, she's transforming 2852 ECu worth of rock-and-what-not into 4324 ECu worth of Disgusting Goop. That might not sound like much, except for the fact that it is effectively a 50% added value just like that in a few minutes (and while I sleep, yes, how else).

The above concrete numbers give me added ECu but also a way of approaching the ever-thorny euloran issue of pricing stuff. Only yesterday it would seem I failed at pricing some WPL correctly since the market (that had ASKED for WPL specifically) decided that... it was too expensive to bother buying it! So no sale made and a fee to pay instead2 but also a very clear and concrete thing to point to next time when anyone asks for WPL or complains that they don't have it.

Regardless of the market being there apparently completely lost in terms of what is how much and why would WPL cost more than dirt-cheap, lowest quality basic stuff, it's still worth to look again at some fresh data and see what prices make sense at all. Taking the Disgusting Goop above, let's calculate precisely what went in and what came out:

input: bundle of quality 595 + blueprint of quality 120 = 5.95*470 + 1.2*47 = 2852 ECu (quality adjusted base value3 )

output: 8 DG of quality 115 = 8*1.15*470 = 4324 ECu (quality adjusted base value)

Output / input = 4324/2852 = 1.51 (i.e. 151% or 51% gain).

Considering that the DG bundle is made only from harvestables4 it follows that Foxy simply can NOT sell those harvestables (rf, cr and sm) at anything less than 150% because at anything less than that she'd be better off using them as input to craft!  Notice also that the basic resources there (rf+cr) make only 2 thirds of the bundle, with sm the other third. For this little exercise I ignored the distinction between basic and non-basic harvestable but mining experience screams loud and clear that non-basic resources ARE harder to get in same quantities and same qualities. Which is not at all surprising given that they have higher value, doh.

As usual, in practice things are indeed a bit murkier, as all sorts of considerations quickly come stomping in: this 50% increase might be obtainable only at this specific sweet spot or only for this specific combination etc. Nevertheless, it IS some concrete data point in a sea of unknowns, so I'll stick to it for now. I'll add also that Foxy is a very skilled crafter (possibly even the top crafter at the moment) and it is for this reason that she *has this option* to make a significant profit just by crafting. Other players might find that the highest profit they can make out of harvestables really is by selling them at less than 150%, why not?

As Foxy's rather busy earning about 1500 ECu every couple of minutes for now, let's leave her aside for a moment and ask simply: what are *you* earning every couple of minutes and what are *your* options really?

  1. Yes, the red messages are all there one on top of the other because the bot is firing requests at the server without pause for clicking, eating, thinking or any of the other human-vices. 

  2. There is a fee for auctions without sale to discourage spam of useless auctions. 

  3. Also known as qabv and in any case the de facto *minimum* value of something in Eulora since that's what you can always get if you sell the item to the merchant NPC (i.e. to S.MG directly). 

  4. harvestables are obtained directly from euloran soil as a result of "mining" activity aka /explore + build; by contrast, craftables are items crafted as above, possibly from harvestables or other craftables 

April 17, 2018

RFC: Eulora's Communication Protocol (EuComms)

Filed under: Eulora — Diana Coman @ 2:59 p.m.

This is a request for public comment (questions, critique, discussion etc) on the current version of Eulora's protocol for client-server communications that has been in works for a while now. Once this public discussion phase ends, the most significant aspects of this protocol will be effectively set in stone, since the procotol is central to any working client for Eulora. Consequently, your chance at having any significant input on it is *now* and only now. Any questions or feedback on it as well as any suggestions or requests related to it are most welcome, warmly appreciated and thoroughly considered *now*. By contrast, any whining and bitching over it at a later time will likely have at most some entertainment value - my entertainment that is. In fewer words: speak now or suffer later, your choice.

1. EuComms: Overall Goals:
1.1. All communications between clients and server to be encrypted.
1.2. Clients to be able to receive from server any data they lack (including maps, skins, sound or video content etcetera), on demand.
1.3. Clients to be able to choose and adjust both the level of security and their volume of communications with the server, as they will ultimately have to pay for the load that they generate.

2. EuComms relies on:
2.1. RSA with Keccak-based OAEP (via EuCrypt) for initial communication of OTPs (Serpent keys).
2.2. Serpent (via EuCrypt) for general communications.

3. Structure:
All communications between server and client will consist of packets up to 4096 bits in length, encrypted either via eucrypt.RSA or eucrypt.Serpent. The complete list of all such packets is included below.

Packets the client may send to the server:
3.1. Initial connection to server : client encrypts with the server's public key and sends to the server a hello message; constructed as follows : following conversation in #trilema log, this hello message would actually end up multi-packet as it has to include the client's public key (n,e so that's currently 4096+2048 bits) instead of the id at 3.1.5 in the structure below:
3.1.1. Octet 0 - the length of the message in octets (43 or 76);
3.1.2. Octets 1 to 8 - the string "EuLoRa";
3.1.3. Octets 9 to 10 - the major and minor versions of the communications protocol that the client wants to use;
3.1.4. Octets 11 to 42 - the client ID string, which will be equal to the eucrypt.keccak hash of the client binary. All client providers will be required to register all their ID strings with Minigame ; connections from clients with unknown ID strings will be rejected. Players will be notified of and helped to identify changes in their client software.
3.1.5. Octets 43 to 75 - the account ID string. If this field is omitted the server will create a new game account for the client.

3.2. Data (client sent)
3.2.1. Octet 0 - the length of the message in octets (multiple of 16 octets);
3.2.2. Octet 1 to 2 - descriptor of the type of data being sent (see annex A for datatypes);
3.2.3. Octet 3 to 5 - three octets ID of the item being sent;
3.2.4. Octet 6 to n - payload.

Packets the server may send to the client:
4.3. Data (server originated)
4.3.1. Octet 0 to 4 - the length of the message in octets (multiple of 16 octets, in principle limited to 65536 altogether and practically in the kbs anyway);
4.3.2. Octet 5 to 6 - descriptor of the type of data being sent (see annex A for datatypes);
4.3.3. Octet 7 to 10 - four octets ID of the item being sent;
4.3.4. Octet 11 to 16 - six octets counter of the chunk being sent (this limits downloadable items somewhat);
4.3.5. Octet 17 to n - payload.

Annex A -- datatypes in client-server communication

NB: all data types below can in principle be sent by both client and server; however, data sent by the client is essentially a request to the server (i.e. it’s up to the server to decide whether it is valid and/or has any effect and/or what effect in game) while same data sent by the server is feedback/information (i.e. it reflects something that *has happened/exists already*).

In fewer words: client proposes, server disposes.

A.0 Basic types (used throughout the rest of sections in this Annex A)
A.0.0. char - character value on 1 octet
A.0.1. text - n*char where n will ALWAYS be specified clearly, right next to each and every text variable passed around
A.0.2. int8 - integer value on 1 octet
A.0.3. int16 - integer value on 2 octets
A.0.4. int32 - integer value on 4 octets
A.0.5. int64 - integer value on 8 octets
A.0.6. float - real value on 4 octets

A.1 Connection
A.1.1 Set of Serpent Keys

  • int8 - number of keys in this set, n;
  • n*(4*int64 + int32) octets - n Serpent keys (32 octets each + 4 octets ID for each, calculated as keccak hash of the 32 octets);
  • int8 - 1 for server use, 2 for client use, anything else undefined currently.

A.1.2 Request Serpent Keys --> response is a "Set of Serpent Keys" (A.1.1)

  • int8 - number of keys requested;
  • int8 - value 1 for server use, 2 for client use, anything else undefined currently.

A.1.3 Choose Serpent Key

  • int32 - ID of the key that will be used for communications from now on (depending on the key's set, it'll be used for server's or client's messages).

A.1.4 Burn & Choose Serpent Key

  • int32 - ID of the key to remove from usable sets;
  • int32 - ID of the key to use for future comms;

A.1.5 Unknown/Malformed Message received

  • int64 - id of message that was not understood.

A.2 File Transfer
A.2.1 File Information

  • int8 - length of file name in octets, n
  • n*char - file name (string)
  • int8 - file type
  • int64 - octets per unit
  • int64 - file size in unit given above
  • int32 - file hash (keccak)

A.2.2 File Content

  • int32 - file hash (keccak)
  • int64 - octets per unit
  • int64 - file size in unit given above
  • unit*file_size*int8 - file content

A.2.3 Request File Information --> response is a "File Information" (A.2.1)

  • int8 - length of file name in octets, n
  • n*char - file name (string)

A.2.4 Request File Content --> response is a "File Content" (A.2.2)

  • int8 - length of file name in octets, n
  • n*char - file name (string)

A.2.5 Request File Information --> response is a "File Information" (A.2.1)

  • int32 - file hash (keccak)

A.2.6 Request File Content --> response is a "File Content" (A.2.2)

  • int32 - file hash (keccak)

A.3 Chat
A.3.1 Chat Public

  • int64 - id of speaker
  • int16 - length of string being said
  • n*char - string being said

A.3.2 Chat Private

  • int64 - id of target for this chat
  • int64 - id of speaker
  • int16 - length of string being said
  • n*char - string being said

A.4 Character Actions & Activities
A.4.1 Basic action

  • int64 - id of subject
  • int64 - id of object
  • int32 - id of action attempted (client-sent)/performed (server-sent) --> see Annex B for list of current basic actions

A.4.2 Item movement

  • int64 - id of subject
  • int64 - id of object
  • int64 - quantity (stack count) to be moved
  • int64 - id of destination object (i.e. own char's id for "pickup", container ID for move to container, sector id for "drop" or move from container to world, other char's id for "trade" or "store" etc.)

A.4.3 Item movement with specified slot

  • int64 - id of subject
  • int64 - id of object
  • int64 - quantity (stack count) to be moved
  • int64 - id of destination object (i.e. own char's id for "pickup", container ID for move to container, sector id for "drop" or move from container to "world", other char's id for "trade" or "store" etc.)
  • int64 - slot id

A.4.4 Activity --> this is meant to be sent by the server;

  • int64 - id of activity
  • int64 - duration (in seconds)
  • int64 - start time (unix format)
  • int8 - status: 0 -> finished/success; >0 -> ongoing / scheduled; <0 -> failed / aborted

A.4.5 Request Activity Information --> response is "Activity" above (A.4.4)

  • int64 - id of requested activity

A.4.6 Train

  • int64 - id of character
  • int64 - id of skill to train

A.5 Environment & Graphics
NB: "requests" here are not actions of the character in the game as such but rather supporting raw API for the client; for instance, requests here include obtaining the id of own character or available maps.

A.5.1 List of Sectors

  • int64 - number of sectors, n
  • n*int64 - list with ids of available sector

A.5.2 Request list of sectors --> response will be "List of Sectors" above (A.5.1)

  • int64 - character ID

A.5.3 Sector Map

  • int64 - id of sector
  • int8 - length of map filename (sector's name)
  • n*char - map filename (sector's name)

A.5.4 Request sector map --> response will be "Sector Map" type above (A.5.3)

  • int64 - id of sector

A.5.5 Item in sector (actor/character or object)

  • int64 - id of item
  • int64 - id of sector in which the item is located
  • float - position of item: x coordinate
  • float - position of item: y coordinate
  • float - position of item: z coordinate
  • int64 - id of graphics profile --> graphics profiles are so that the client can request and choose from alternative/equivalent actual files/meshes/icons/animations for this particular graphics profile
  • int8 - length of name/label of item
  • n*char - name/label of item

A.5.6 Request own char --> no payload here really since it's accepted only from authenticated client so unambiguous anyway; response will be a "Item in sector" type above - it includes id of sector + id of char etc. (A.5.5)

A.5.7 Item in container

  • int64 - id of item
  • int64 - count
  • int64 - parent item/actor id (i.e. inventory is simply actor-as-container)
  • int64 - slot id
  • int64 - id of graphics profile --> same story as at A.5.5 above
  • int8 - length of name/label of item
  • n*char - name/label of item

A.5.8 Request item --> response will be "Item in sector" or "Item in container" types above (A.5.6, A.5.7)

  • int64 - id of item

A.5.9 Item Text Description (returned in response to a "view" basic action)

  • int64 - id of item
  • int64 - length of description
  • n*char - text description

A.5.10 Item Text Content --> sent in response to "read" basic action

  • int64 - id of item
  • int64 - length of text content
  • n*char - text content

A.5.11 Item List of Characteristics

  • int64 - id of item
  • int16 - number of characteristics
  • n*int64- the ids of relevant characteristics for this item

A.5.12 Item Characteristic

  • int64 - id of item
  • int64 - id of characteristic
  • int64(/float/int32/int16/char) - value of characteristic --> type here would depend on characteristic according to definition at A.5.13 below

A.5.13 Characteristic

  • int64 - id of characteristic
  • int8 - type of value of this characteristic (see A.0 above for the ids of data types that can appear here)
  • int64 - length of name of characteristic, n
  • n*char - name of characteristic
  • int64 - length of name of category, c
  • c*char - name of category

5.14 Request Characteristic --> response is "Characteristic" above (A.5.13)

  • int64 - id of requested characteristic

A.5.15 Skill

  • int64 - id of skill
  • int64 - length of skill name
  • n*char - skill name
  • int64 - length of skill's category name
  • c*char - category name

A.5.16 Skill List

  • int 64 - number of skills in this list
  • n*int64- ids of skills in this list

A.5.17 Character's Skill

  • int64 - id of character
  • int64 - id of skill
  • int64 - current rank
  • int64 - current knowledge points
  • int64 - current practice points
  • int64 - cost of knowledge to next rank
  • int64 - cost of practice to next rank

A.5.18 Request Skill Information --> response will be Skill above (A.5.15)

  • int64 - skill id

A.5.19 Request List of Skills --> response will be Skill List above (A.5.16)

  • int64 - id of character whose skills are requested

A.5.20 Request Character's Skill --> response will be Character's Skill above (A.5.17)

  • int64 - id of character whose current skill values are requested
  • int64 - id of skill requested

A.5.21 Time of day (game time)

  • int8 - hour
  • int8 - minute

A.5.22 Request time of day (game time) --> no payload, response is Time of day above (A.5.21)

A.5.23 Movement Type

  • int64 - id of this movement type
  • int64 - id of graphic profile for this movement type
  • float - x change
  • float - y change
  • float - z change
  • float - x rotation
  • float - y rotation
  • float - z rotation
  • int64 - length of name
  • n*char - name of this movement type

A.5.24 Request movement type --> response will be "Movement Type" above (A.5.23)

  • int64 - id of requested movement type

A.5.25 List of movement types

  • int64 - number of available movement types
  • n*int64- list of ids of available movement types

A.5.26 Request list of movements --> response will be a "List of movement types" above (A.5.25)

  • int64 - id of item for which available movement types are requested

A.5.27 Set Movement Type

  • int64 - id of item for which movement type is set
  • int64 - id of movement type to set

A.5.28 Destroy Item

  • int64 - id of item that is destroyed/vanishes

A.5.29 Set Item Position

  • int64 - id of item
  • int64 - id of sector in which the item is located
  • int8 - position of item: x coordinate
  • int8 - position of item: y coordinate
  • int8 - position of item: z coordinate

A.5.30 Neutral message --> mainly for feedback e.g. "X killed himself", "That tool is not useful anymore", "You ranked up.", "You got loot"

  • int64 - length of text in characters, n
  • n*int8 - text

A.5.31 Error message (in game)

  • int64 - length of text in characters, n
  • n*int8 - text

A.5.32 Success message (in game)

  • int64 - length of text in characters, n
  • n*int8 - text

A.5.33 Message of the day

  • int64 - length of text in characters, n
  • n*int8 - text

A.5.34 Request message of the day --> no payload here; answer will be "Message of the day" above (A.5.33)

A.5.35 Top

  • int64 - duration in days from game's "today" (i.e. 0 for today's top, 30 for past months' top etc.)
  • int64 - length of text in characters, n
  • n*int8 - text

A.5.36 Request Top --> answer will be "Top" above (A.5.35)

  • int64 - duration in days from game's "today" (i.e. 0 for today's top, 30 for past months' top etc.)

A.5.37 Graphics Profile

  • int64 - id of this graphics profile
  • float - width
  • float - height
  • float - depth
  • int64 - number of contained slots with their own graphics profiles
  • int8 - length of filename for icon
  • m*int8 - icon filename
  • int8 - length of filename for mesh
  • n*int8 - mesh filename
  • int8 - length of filename for texture
  • p*int8 - texture filename
  • int8 - length of filename for animation
  • q*int8 - animation filename
  • int8 - length of filename for sound
  • r*int8 - sound filename

A.5.38 Request Top-Level Graphics Profile --> response is "Graphics Profile" above (A.5.37)

  • int64 - id of requested graphics profile

A.5.39 Request Child Graphics Profile --> response is "Graphics Profile" above (A.5.37)

  • int64 - length of path (i.e. how deep in the hierarchy is the graphics profile of interest)
  • n*int64- ids forming the path to the desired graphics profile (e.g. 2,1,15 means the 15th slot of the 1st slot of top graphics profile number 2).

Annex B - List of currently available basic actions

B.1 Target --> this is less than View at B.2. below; character targets the object.

B.2 View --> this is a generic view and can be applied to anything (objects, actors, world included).

B.3 Read

B.4 Lock/unlock

B.5 Use/Combine/Sacrifice

B.6 Explore (current /explore, with target sector id)

B.7 Repair

B.8 Exchange --> this would be used for at least 3 currently distinct parts: trade, store, bank. As everywhere else, its exact effect depends on context.

B.9 Complete --> for actions that require explicit "accept" confirmation from player (e.g. trade)

B.10 Abort --> aborts what the character is doing (if the abort is possible, permitted and meaningful in the given context).

B.11 Attack --> for current "/die" simply use this with subject and object the same, namely own character.

Use the comment form below for any questions, comments, suggestions or desires you have regarding this communications protocol.

May 3, 2017

Quest for the Crafty Noob

Filed under: Eulora — Diana Coman @ 5:19 p.m.

Eulora is this game where players get to actually do... everything. Even give quests to other players, when they want to and as (or if!) they like it. No more "bring me 7 rats' tails and I'll give you a rat's ass" a la every other RPG out there but good old fashioned elder talking1: here son, take ye olde blueprint and craft yourself a table first if you are serious about actually doing something in this life!

The table in question is not any table but the very useful and extremely versatile craft-table that Foxybot uses to carry stuff around when one doesn't use it to craft or to store or to expand one's inventory. And so the quest goes like this:

Find Foxy in game and ask her for the Crafty Noob's first quest. Ask her nicely for she is under no obligation to give the quest to you! If she is however of a nice enough disposition to give you a helping hand, she'll give you a few items, including a craft-table blueprint that reads like this:


She'll also give you a bit of advice: take those items and go find the public crafting table that is close to one NPC called Electron Spirover, up a rocky hill. Once there, figure out how to use the things she gave you (as well as other bits that you might need but can find yourself with a bit of /explore) and make yourself your very own Craft-table!

As a bonus, you might even get some numina in the process. Or at least find out that you... could have gotten some numina such as Petrified Feelings. If only you knew how and why or when one gets such things...

  1. Do you even still find this in *real* life around you? Did you ever look for it? 

Older Posts »

Theme and content by Diana Coman