Infinite-sized world

Here’s why.

What if you could build your town on a flying island, and then rather than have the Game Master send Cthulhu at you, you seek out Cthulhu in your flying doom fortress? I’ll be honest, I never liked that thing they do in games, where you’re fighting a huge boss with tiny people using tiny swords that seem like the worst they’ll do is clip the monster’s nails. A great monster needs a great weapon to be defeated. Sure, you could go through a quest to get the Holy Book of Smiting or something and then cast a great big flashy spell to kill the creature… but what if you could also do it the hard way, by, say, dropping boulders on the monster’s head? Pouring lava on it? Firing a huge armageddon cannon at it?

Stonehearth wants us to design a smoothly working town. I say, let us use that as a weapon in itself. It wouldn’t be easy to pull it off, of course, you have to make sure to have enough rocks to drop, to have solid lavaducts in place that lava won’t overflow your town, to make sure the doom cannon is fully powered… a large, efficient crew is needed for this. Why limit the slaying of monsters to heroes when it could be the whole town’s credit?

This is in addition to possibilities such as sailing and nomadic-style play with a group of cityless Hearthlings.

I’m not yet familiar enough with Stonehearth’s deeper workings to know whether this can be modded in or not, but something tells me that real-time procedural generation capability (a la Minecraft) is an engine feature that us mortals cannot reach. I don’t know, though: experienced modders can feel free to correct me (pinging @honestabelink, @Relyss, @RepeatPan and @Albert, since I understand he worked on world generation code).

What do you guys think? Do you like the idea of a travelling, flying city, or do you think it’s against Stonehearth’s spirit?

5 Likes

I think that this would fit perfectly. The spirit of stonehearth is kind of more funny and wacky than anything. I think it’d be great, but first we need to get the boring, regular stuff, like goblins and rivers and such. But yes, this is something I’d really like to see if the game progresses that far.

3 Likes

Correct me if I’m wrong, but wasn’t infinite worlds part of the plan already?

Though a floating fortress that can move about the world might be a bit of a stretch.

Currently I don’t think there’s any point. You build a city and bang, update.

you are correct… the intent is to have an “infinite” map at some point…

5 Likes

Sweet! I didn’t know that.

It does sound that way, but hmm… I mean, if it’s possible to have an extra navgrid (the floating city one) that can move freely above the “actual” navgrid on the ground, it shouldn’t affect citizens’ pathing too much.

As with all things Alpha, it’s only a matter of time until this is no longer the case. The first Alpha 8 dev build was really stable and fun for me. My most successful settlement lasted 22 days. It broke again for now, but hey, such is Alpha. For now I’m doing more modding than playing anyway, so it all works out.

P. S. Also, having browsed Castle Story’s and Cube World’s reddit last night, it’s still quite surreal to hear people complain about regular updates o_O

4 Likes

I migrated here from Castle Story myself. There’s a game which really annoyed me. In the time it’s been available in Steam there has been no new content, no new staff. I might be wrong here but apparently Castle Story was/is a learning experience for the Devs. Instead of hiring people who know what they’re doing to bring the game to completion.

Edit: Modding is a bit part of this game or at least will be when saves aren’t version specific

1 Like

There’s no “world generation phase”, so terrain can be generated on-the-fly. This is not currently done, however, because the whole world generation is subject to a major overhaul as far as I know.

For all intents and purposes, it would already be possible to generate new “chunks” (the game is organized in tiles too, they’re just not as easy visible as Minecraft’s chunks). Doing this, however, would be messing with the world generation code itself a lot, which is quite frankly something I don’t even intend on remotely doing. Messing around with the landscaper was deep enough for me, thank you very much, I don’t need three layers of filters-over-noise-functions even if it does produce pretty neat looking terrain.

6 Likes

they aren’t right now, if you load an old save in a new update your just bound to have lots of bugs.

1 Like

Yeah but they don’t work properly so you could still argue they’re locked to the game version it was created with.

1 Like

If it wasn’t for the engine stability issues right now I would say that this would be a huge feature to add standardized file schema that can be loaded into future saves.

Not really.


Disclaimer: I’m by no means an expert on SH’s save game mechanics but the odds and bits from reading a few dozen lua files.


What most people here don’t seem to know is that the save games already are universal. Really, take a look at anything that saves: It’s not a series of WriteInt() WriteInt() WriteInt(); ReadInt() ReadInt() ReadInt() or the like which would justify “Yeah, so well, we added one number to the game so your savegame is incompatible.” The save game data is already stored in an associative array (a lua table).

Technical mumbo jumbo

Technically, there’s nothing that prevents you from loading older savegames into the game, or newer ones and in certain cases, the game likely wouldn’t even notice at all if it wasn’t remembering which version the save game has.

The trouble comes from the fact that the game isn’t finished, and won’t be for a long time. Variable renamings and code refactorings happen all the time (to add new features or improve code quality) and those break save game compatibility.

If you’re familiar with Minecraft and its mods, it’s about the same thing. Mods break with every game version and it’s not because Minecraft has changed so radically, it’s likely because the mod author (or their API) has done some house keeping and waited for a new major release (when people start new maps anyway) to release them.

An example of a breaking (but necessary) change

Example: Let’s imagine we have a bucket that can contain water. We’re storing the amount of water it has in a variable called water_level. Of course, save games that had a bucket but no water_level will no longer work (because the game won’t set water_level, which will cause it to look a bit dazzled when something asks it the contents of the bucket).

A few revisions later, we’ll also add, oh, berry juice which can also be put into buckets. Now, because that wouldn’t be water anymore, the variable is renamed to fluid_level, therefore becoming universal (improving code quality by refactoring). If you load an older save game, the game will set the variable water_level, but the current game will look at fluid_level (which then won’t be set) - ergo, the item becomes erroneous.

This is one of the most common things about why save games break between different revisions.

Can this be avoided?

Avoiding this kind of error takes a lot of (in my humble opinion) unnecessary resources.

Basically, to have backwards compatibility (loading older saves), you need to think of everything that happened to this entity since the last revision. For example, our bucket would need code à la self._fluid_level = self.__sv.fluid_level or self.__sv.water_level. Now you add this kind of code for every variable that changed. For all revisions that did.

These are the simple cases, too. What if I store things as a numeric array and later switch to a associative array? What if I store entities relative to my position at first and later relative to the world’s origin?

This will create rather huge and ugly “migration code” that will only serve the purpose of transitioning savegames from one version to another. In my opinion, this isn’t justified at all. The game is not even a beta yet, so I don’t see a reason why there should be taken extra care to keep save games working across (completely different) builds. Of course I don’t intend to say that they shouldn’t try to do it wherever possible and doable with reasonable effort, but going the extra mile for this seems useless.

4 Likes

I understand that save game files are not a bunch of read and writes of data without data Your comment about backwards compatibility is not accurate, you do not need to track every change as you state you just need default values. The problem is you need a relatively stable schema to do this effectively, ie you don’t change waterlevel in the input object to level. For example (in python since it is the language I use most often):

class WaterBucket():
	def __init__(self, water_level=0, in_data=None):
		self.water_level = water_level
		self._in_data = in_data
		if self._in_data:
			self.load_from_data()

This will not create backwards compatible saves, this will merely give the illusion of doing so (by preventing any sort of data error - logic errors still apply). Example: We have an entity with a default color (“red”) that can be changed by applying paint. If we paint it now (“blue”) and the game changes its naming, there are three scenarios:

  • The game does not know about the change (the current situation), the color is either red (if the component was initialized again) or nil, therefore resulting in undefined behaviour.
  • The game does know about the change and can correctly map the old variable to the new one. The color is blue. This is the big, wasteful approach that is in my opinion not justified in an alpha.
  • Your approach initializes the object again as red, then ignores the original color (because it was saved in a different, unrelated and now unused variable).

In addition, as I’ve mentioned, save games are tables and may contain lots of variables, including nested ones. Lua has a maximum of 100 parameters per function (by default) and no concept of default values, leave alone anything defaulty for tables.

A better example would be where you have two variables, has_something and something. If it’s renamed to something_else and you load a save game with has_something = true, something = {}, your game will still throw exceptions because logically, something_else ought to be valid (as implied by has_something)

tl;dr: Default values are no solution due to the complexity (nested values), missing language features (default parameters) and the obvious reason that mixing default values and save game values is a big no-go.


That aside, as I’ve mentioned in the editor discussion, setting a fixed anything for the game is severely handicapping it from improving. Because save games are not just some kind of archive you put data in solely when saving or loading (they are transparent lua tables that are accessed at runtime all the time), setting a fixed schema will effectively degrade code quality. You can’t name it water_level in the save game and fluid_level in the code.

My premise was about a relatively stable schema, giving a counter argument that violates that premise invalidates your attempt to counter. Yes if you have a dynamic schema where you go back and change previously coded values like you just suggest it would not work.

We are not dealing with language files, if you are storing language values or language tags in your saved files you having very poor coding standards. The only thing that could be store in a saved game should be a reference to your prefered language tag. And in a game this should be stored in profile or application settings.

This is completely false and not even based one what I said, I said nothing about a fixed schema, I said a relatively stable schema, this is not the same as a fixed schema. This means once you are done setting your schema for a water bucket exists:

WaterBucket:
	Damage = Short
	Name = String
	Owner = HearthlingID

Now you want to expand this to include a water level, so you add this water level, this is fine you schema is still stable:

WaterBucket:
	Damage = Short
	Name = String
	Owner = HearthlingID
	WaterLevel = Short

Now you decide that Damage is a bad variable name, you want it to be health, so you change it. This is not alright your schema is no longer stable:

WaterBucket:
	Health = Short
	Name = String
	Owner = HearthlingID
	WaterLevel = Short

Again very little of what you said was actually in response to what I said and while some of it was factually correct in context to what you read it was not what i have been discussing. Also default values loaded by the class in modern coding languages are required via proper coding practices. Sometimes these default values will error, like the Owner’s default value would cause and error as it should.

Minecraft is a great example of a stable schema, if you upgrade your Minecraft version your save games still exist and work. Not all the features may be available such as biomes in previously generated data; however the stable schema allows you to continue playing your saved game across multiple versions of the game without expensive backporting code.

When talking about Minecraft, I wasn’t referring to the base game but rather mods. The base game is very stable, yes, but the mods switch around all the time. Minecraft’s base game cannot be compared to Stonehearth in any way except maybe the very engine itself in terms of complexity.

Which isn’t true either. Minecraft has at least twice changed its file format which required it to convert their map files.

The thing is still that there exist no schemas, not even dynamic ones - at least in the sense that you think they should. Stonehearth’s save system is literally just a magic lua table that is serialized and deserialized with very little to no user interaction (i.e. the only thing you actually need to do is mark the table as modified I believe).

You’re completely ignored that the save game data is also runtime data, therefore providing a “stable schema” comes at the cost of having outdated and unfitting variable names and/or data structures at runtime. This is not just an issue of “adjusting the save and load function”.

Great, two issues: First, lua is as simple as any powerful scripting language can probably be, and second, it’s not exactly modern. The class system that Stonehearth employs is somewhat wonky, but it works for what it’s supposed to do. At the end of the day though, the whole game is just a bunch of glorified tables.

Minecraft, the basic game, does not require a lot of code because there isn’t much to save: Most of the game fits into a 32bit integer (or less). In addition, the game is complete, therefore there aren’t any major changes to be expected.

Minecraft mods on the other hand change all the time, are barely backwards compatible with the last version (even the “proper” established mods which are not just some common thing). They are more comparable to Stonehearth: the code is still in flux and agreeing on any kind of standard at this phase can hurt the game’s development. This is one of the reasons, I believe, why Radiant is not officially endorsing messing around with lua (or about anything that has no real API as of yet - which probably boils down to mixintos, overrides, scenarios and maybe craftable items): If they did, they had to take all these promises into consideration.

In the end, having a fixed schema as you imagine it will be almost impossible:

  • There is no definition of a schema. I can literally access new variables in every function. I’m not required to initialize the variables at any point (which fits nicely with lua’s design).
  • Because the save variables are just another table (that is persistent), naming of these variables and structure of its data matters. I cannot, for compatibility’s sakes, call a variable water_level even if it’s fluid_volume by now without referring to water_level everywhere in the code. Of course you can circumvent that with metamethods and indexers and what not, but this is seriously going too far.
  • I don’t see the point in an alpha in all honesty. Having persistent variables in the game currently is extremely (I’m almost tempted to say ridiculously) easy, which comes at a cost. Combined with lua’s nature (that every undefined variable is nil), having initializers or what not is next to impossible for all possible scenarios (for example, if every uninitialized field was attempted to initialize again (which, still, is a horrible idea), it would be impossible to save nil).
  • The lack of serializing/deserializing callbacks is only making things more complicated. Although we could argue that there is a deserializing callback (namely, it seems that the object is created, then populated with save game data, and then initialize is called - at least for components and services), there’s none for serializing.

Please tell me how a stable schema, at this point in development, is outweighing the disadvantages that I’ve mentioned above. We’re not talking about a released game here, nor are we talking about some piece of academic software - we’re talking about a game alpha that has a thousand other things that need to be taken care of instead of further restrictions.

You are not reading my post and you have seriously lack fundamentals in modern programming standards, games or not. You have also consistently posted where 1/2 of what you are talking about is out of context of what I have said and in the context you want it to be in, great example you keep referring to Fixed Schema when I have not stated anything about Fixed Schema.

Either that or you are just trolling, either way I’m not going to be responding to this unproductive conversation anymore.

I am reading your posts, I just can’t see anything new in it.

Judging by the fact that I have no background in computer science whatsoever, that’s a possibility. Then again, as I’ve hinted at, we’re not in a competition to see who can come up with the most modern algorithms or implementations of anything. At the end of the day, there should be a solid product. Whether it’s a member of the Church of insert the newest fad in programming here doesn’t matter for the player and likely not even for the majority of modders. It’s all nice and dandy on the paper and I guess it makes a great entry in your résumé if you can say “wrote a game using newest technology” (or hell, even modern), but it’s not required at all.

I am not talking “out of context”, I’m bringing in examples from other sources. It can’t hurt to see how others have solved a problem, how they have succeeded and how they have failed. In Minecraft’s case - I’m sorry to bring this up again, but the core concept fits nicely: It has mods (sort of), it’s storing the data as associative array with no strict (“fixed”, “stable”, whatever you may call it - to me, it’s the same) schema and last but not least it’s a mess.

I’m sorry that I have not called them “stable schemas” but instead “fixed schemas”, which to me is the same. I would have assumed that given that there is no official lingo it would become clear from the context. Alas, this wasn’t the case (probably because I’m “out of context” half the time?).

The conversation was from my point of view unproductive from the very start because what you are proposing (and let me quote this, a “standardized file schema”) is completely unusable in the current (and probably future) savegame mechanic (it’s simple lua tables, not protobuf or similar). That you think that transforming data from one structure to another “just need[s] default values” and that this would effectively solve the problems (given a “stable schema”, which shouldn’t exist yet) is just another example of it.

I’m not a troll, but I think we’re doing a very fine job of ignoring each other.

sorry i dont know if it will fit here, and i dont know if it has already been suggested, but… i thought i heard (in a Let’s Play video) somewhere that you guys are going to be adding the fact that the random map we are given at the start will be our 8entire* world… so we can explore all of it???

Please implement this :slight_smile:

Technically, nothing limits you to that map though. Additional tiles could be generated at ease.