Thanks to the developers! (& suggestion for savegames)

impaktor
Posts: 1029
Joined: Fri Dec 20, 2013 9:54 am
Location: Tellus
Contact:

Re: Thanks to the developers! (& suggestion for savegames)

Post by impaktor »

jpab wrote:That's just my opinion though. I don't know how other people feel about it.
People are lazy and curious, and once someone finds out how to cheat they'll probably do it, and that pretty much kills the joy of a game in my opinion. You want to put in that hard work to get that cool ship or that special laser. Now, if you can just give yourself money, that motivation will die and it makes the game less fun, I think.

In Doom and Wolfenstein you at least got a punishment when cheating by resetting your score if I remember correctly. Well, I don't have any experience with cheating other than that.

Yet I think it sounds like a good idea to keep everything in plain text for now and the foreseeable future, and then at some point, when we're happy with the save format, just compress it as jpab suggested and that will steer most people clear from the obvious path of cheating.

Keep up the good work nick!
nick
Posts: 85
Joined: Mon Sep 08, 2014 9:24 pm
Location: Plymouth, UK

Re: Thanks to the developers! (& suggestion for savegames)

Post by nick »

It's human nature to value something more if one's had to strive for it ;)

Going to download the Visual Studio 2013 Express ISO overnight (my VS 2008 won't open the Pioneer solution).
4.7 GB !!! I hope it'll be done by 9am :S (My internet connection is not great, and I have to disconnect it during the day). Ideally I want a download that can be paused and restarted.
Would anyone recommend using the "Install now" option? (instread of the ISO) - perhaps it's a smaller download? Still can't interrupt it though.

[edit] Download of Visual Studio 2013 Express ISO has failed, with 8 hours still to go. Trying the "install now" option, with the non-pausable download program. Fingers crossed :)
[edit] All done, the download wasn't so big after all.

Cheers,
Nick
nick
Posts: 85
Joined: Mon Sep 08, 2014 9:24 pm
Location: Plymouth, UK

Re: Thanks to the developers! (& suggestion for savegames)

Post by nick »

Hi,

I understand the current savegame process reasonably well now.
I have a couple of questions about the data:

What are "Frames"?
Frames of reference? Sfx (sound effects?) is in the Frames section. The root frame has child frames, and the serialization is recursive.

Hyperspace Clouds:
Contain pointer to a *copy* of associated ship? Not the ship itself?
I need to trace this one out in detail - I could easily be missing something :)

Thanks,
Nick

Here's the data that currently gets saved:

Code: Select all

Leading Signature characters [Byte] "PIONEER"
Version [Int32]
Galaxy Generator
	Section Label [String] "GalaxyGen"
	Name [String]
	Version [Int32]
Game State
	Section Label [String] "Game"
	Time [Double]
	State [Int32] STATE_NORMAL | STATE_HYPERSPACE
	Want Hyperspace [Bool]
	Hyperspace Progress [Double]
	Hyperspace Duration [Double]
	Hyperspace End Time [Double]
Space, Bodies and Things
	Section Label [String] "Space"
	Star System
		if(exists)
			Lead Char [Byte] 1
			Sector X [Int32]
			Sector Y [Int32]
			Sector Z [Int32]
			System Index [Int32]
		else
			Lead Char [Byte] 0
	Frames
		Section Label [String] "Frames"
		Flags [Int32]
		Radius [Double]
		Label [String]
		Pos [Vector3d]
		Ang Speed [Double]
		Initial Orient [Double] (9 of these)
		Index for System Body [Int32]
		Index for Body [Int32]
		Children Size [Int32]
		Children (multiple)
			Recursive serialization of Frames
		Sfx Num Active [Int32]
		Sfx (multiple – up to MAX_SFX_PER_FRAME)
			Pos [Vector3d]
			Vel [Vector3d]
			Age [Float]
			Type [Int32]
	Bodies Size [Int32]
	Bodies (multiple)
		Section Label [String] "Body"
		Type of Body [Int32]
		Properties [String] STAR | PLANET | SPACESTATION etc...
		Index for Frame [Int32]
		Label [String]
		Dead? [Bool]
		Position [Vector3d] (3 Doubles)
		Orientation [Double] (9 of these – 3x3 matrix)
		Phys Radius [Double]
		ClipRadius [Double]
		Body derived-class-specific data
			Lots of data...
	Index of Player Body [Int32]
Hyperspace Clouds
	Section Label [String] "HyperspaceClouds"
	Number of Clouds [Int32]
	Hyperspace Cloud (multiple)
		Section Label [String] "Body"
		Type of Body [Int32] HYPERSPACECLOUD
		Properties [String]
		Index for Frame [Int32]
		Label [String]
		Dead? [Bool]
		Position [Vector3d] (3 Doubles)
		Orientation [Double] (9 of these – 3x3 matrix)
		Phys Radius [Double]
		ClipRadius [Double]
		Body derived-class-specific data
			Vel [Vector3d]
			Birthdate [Double]
			Due [Double]
			IsArrival [Bool]
			Ship Exists [Bool]
			if(exists)
				Ship data (for ship associated with hyperspace cloud)
System Political Data
	Section Label [String] "Polit"
	Criminal Record Size of Dict [Int32]
	Criminal Record Dict Entry (multiple)
		Sector X [Int32]
		Sector Y [Int32]
		Sector Z [Int32]
		System Index [Int32]
		Body Index [Int32]
		Data (Sint64) [Auto]
	Outstanding Fine Size of Dict [Int32]
	Outstanding Record Dict Entry (multiple)
		Sector X [Int32]
		Sector Y [Int32]
		Sector Z [Int32]
		System Index [Int32]
		Body Index [Int32]
		Data (Sint64) [Auto]
	Player Per Bloc Crime Record
		Size [Int32]
		Entry (multiple)
			Record [Int64]
			Fine [Int64]
Views
	Section Label [String] "ShipCPanel"
	Scanner Mode [Int32]
	Scanner Current Range [Float]
	Scanner Manual Range [Float]
	Scanner Target Range [Float]
	Cam Button [Int32]
	Section Label [String] "SectorView"
	Pos X [Float]
	Pos Y [Float]
	Pos Z [Float]
	Rot X [Float]
	Rot Z [Float]
	Zoom [Float]
	In System [Bool]
	Current
		Sector X [Int32]
		Sector Y [Int32]
		Sector Z [Int32]
		System Index [Int32]
		Body Index [Int32]
	Selected
		Sector X [Int32]
		Sector Y [Int32]
		Sector Z [Int32]
		System Index [Int32]
		Body Index [Int32]
	Hyperspace Target
		Sector X [Int32]
		Sector Y [Int32]
		Sector Z [Int32]
		System Index [Int32]
		Body Index [Int32]
	Match Target to Selection [Bool]
	Automatic System Selection [Bool]
	Detail Box Visible [Bool]
	Section Label [String] "WorldView"
	Cam Type [Int32]
	Internal Camera Controller
		Mode [Int32]
	External Camera Controller
		Rot X [Double]
		Rot Y [Double]
		Dist [Double]
	Sidereal Camera Controller
		Side Orient [Double] (9 of these)
		Dist [Double]
Lua
	Section Label [String] "LuaModules"
	Pickled [String]
Trailing Signature characters [Byte] "END"
Last edited by nick on Mon Oct 20, 2014 6:38 pm, edited 1 time in total.
FluffyFreak
Posts: 1344
Joined: Tue Jul 02, 2013 1:49 pm
Location: Beeston, Nottinghamshire, GB
Contact:

Re: Thanks to the developers! (& suggestion for savegames)

Post by FluffyFreak »

Frames are indeed frames-of-reference, there's always one centered on the systems star, others around the planets/moons/stations etc.
nick
Posts: 85
Joined: Mon Sep 08, 2014 9:24 pm
Location: Plymouth, UK

Re: Thanks to the developers! (& suggestion for savegames)

Post by nick »

Thanks. Now I think about it, it does make sense to have sfx in frames section (the sounds that are heard from the frame of reference).
nick
Posts: 85
Joined: Mon Sep 08, 2014 9:24 pm
Location: Plymouth, UK

Re: Thanks to the developers! (& suggestion for savegames)

Post by nick »

I know enough about the savegame process to start thinking about how to implement the new system.

My thinking is as follows:

We need a savegame format that is a tree, the ability to navigate nodes, return the number of child nodes, iterate through the nodes etc. There are two obvious choices: XML and JSON. I'm favoring JSON, because its easier to read - what do you think? I believe either can be platform independent.

The new savegame system will need some basic functions written for node navigation, and reading and writing the various data types (relatively painless - barring the "auto" type, but will cross that bridge when come to it).

I've examined the code enough to implement a node-based structure of the existing save data - is this what you have in mind?

The structure of a samegame file will be essentially the same as the existing one, but written in a hierarchical tree structure (nodes containing data, nested inside other nodes etc). Each node type will have a name.

Saving the number of objects (as int32) before saving the objects will no longer be required, because we can call the "get number of nodes function", and/or just iterate through the objects. The tree will be quite deep.

Future savegame formats will have new node types. When loading an older file, the new version code should create a default/nominal value (e.g. when looking for a node "colour of crew hats" that did not exist in the old savegame file version).

So it would seem that the remaining tasks before coding, are to learn JSON and pick a JSON parser. However, I do feel a bit out of my depth, what with work commitments and my other software project (a computer algebra system). I can't say when I'll get this task completed I'm afraid. I'll probably need a bit of help with some unfamilliar aspects of software development.

Following on from the [existing] savegame process pseudocode (see 3 posts above) the savegame process for all the "body" types in Pioneer is shown below:

Body <- TerrainBody <- Star

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] STAR
TerrainBody::Save
	Body::Save
		Properties [String]
		Index for Frame [Int32]
		Label [String]
		Dead? [Bool]
		Position [Vector3d] (3 Doubles)
		Orientation [Double] (9 of these – 3x3 matrix)
		Phys Radius [Double]
		ClipRadius [Double]
	Index for System Body [Int32]
Body <- TerrainBody <- Planet

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] PLANET
TerrainBody::Save
	Body::Save
		Properties [String]
		Index for Frame [Int32]
		Label [String]
		Dead? [Bool]
		Position [Vector3d] (3 Doubles)
		Orientation [Double] (9 of these – 3x3 matrix)
		Phys Radius [Double]
		ClipRadius [Double]
	Index for System Body [Int32]
Body <- HyperspaceCloud

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] HYPERSPACECLOUD
HyperspaceCloud::Save
	Body::Save
		Properties [String]
		Index for Frame [Int32]
		Label [String]
		Dead? [Bool]
		Position [Vector3d] (3 Doubles)
		Orientation [Double] (9 of these – 3x3 matrix)
		Phys Radius [Double]
		ClipRadius [Double]
	Vel [Vector3d]
	Birthdate [Double]
	Due [Double]
	IsArrival [Bool]
	Ship Exists [Bool]
	if(exists)
		Ship data (for ship associated with hyperspace cloud)
Body <- Projectile

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] PROJECTILE
Projectile::Save
	Body::Save
		Properties [String]
		Index for Frame [Int32]
		Label [String]
		Dead? [Bool]
		Position [Vector3d] (3 Doubles)
		Orientation [Double] (9 of these – 3x3 matrix)
		Phys Radius [Double]
		ClipRadius [Double]
	Base Vel [Vector3d]
	DirVel [Vector3d]
	Age [Float]
	Lifespan [Float]
	Base Dam [Float]
	Length [Float]
	Width [Float]
	Mining [Bool]
	Color [Color4UB]
	Index for Body [Int32]
Body <- ModelBody <- SpaceStation

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] SPACESTATION
SpaceStation::Save
	ModelBody::Save
		Body::Save
			Properties [String]
			Index for Frame [Int32]
			Label [String]
			Dead? [Bool]
			Position [Vector3d] (3 Doubles)
			Orientation [Double] (9 of these – 3x3 matrix)
			Phys Radius [Double]
			ClipRadius [Double]
		IsStatic [Bool]
		Colliding [Bool]
		Model Name [String]
		Model
			SaveVisitor?
			Animation (multiple)
				Animation Progress [Double]
			Cur Pattern Index [Int32]
		Shields
			Enabled [Bool]
			Size [Int32]
			Shield (multiple)
				ColorR [Byte]
				ColorG [Byte]
				ColorB [Byte]
				Name [String]
	Ship Docking Size [Int32]
	Ship Docking (multiple)
		Index for Body [Int32]
		Stage [Int32]
		Stage Pos [Float]
		From Pos [Vector3d]
		From Rot [Quaternionf]
	Ports Size [Int32]
	Ports (multiple)
		Min Ship Size [Int32]
		Max Ship Size [Int32]
		In Use [Bool]
		Bay IDs Size [Int32]
		Bay (multiple)
			ID [Int32]
			Name [String]
	Index for System Body [Int32]
	Num Police Docked [Int32]
	Door Animation Step [Double]
	Door Animation State [Double]
	Navlights
		Time [Float]
		Enabled [Bool]
		Color [Byte] (Unknown number of these)
Body <- ModelBody <- ShipCockpit

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] OBJECT? Doesn't work
ModelBody::Save
	Body::Save
		Properties [String]
		Index for Frame [Int32]
		Label [String]
		Dead? [Bool]
		Position [Vector3d] (3 Doubles)
		Orientation [Double] (9 of these – 3x3 matrix)
		Phys Radius [Double]
		ClipRadius [Double]
	IsStatic [Bool]
	Colliding [Bool]
	Model Name [String]
	Model
		SaveVisitor?
		Animation (multiple)
			Animation Progress [Double]
		Cur Pattern Index [Int32]
	Shields
		Enabled [Bool]
		Size [Int32]
		Shield (multiple)
			ColorR [Byte]
			ColorG [Byte]
			ColorB [Byte]
			Name [String]
Body <- ModelBody <- DynamicBody <- CargoBody

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] CARGOBODY
CargoBody::Save
	DynamicBody::Save
		ModelBody::Save
			Body::Save
				Properties [String]
				Index for Frame [Int32]
				Label [String]
				Dead? [Bool]
				Position [Vector3d] (3 Doubles)
				Orientation [Double] (9 of these – 3x3 matrix)
				Phys Radius [Double]
				ClipRadius [Double]
			IsStatic [Bool]
			Colliding [Bool]
			Model Name [String]
			Model
				SaveVisitor?
				Animation (multiple)
					Animation Progress [Double]
				Cur Pattern Index [Int32]
			Shields
				Enabled [Bool]
				Size [Int32]
				Shield (multiple)
					ColorR [Byte]
					ColorG [Byte]
					ColorB [Byte]
					Name [String]
		Force [Vector3d]
		Torque [Vector3d]
		Vel [Vector3d]
		AngVel [Vector3d]
		Mass [Double]
		Mass Radius [Double]
		Ang Inertia [Double]
		IsMoving [Bool]
	Cargo [String]
	Hit Points [Float]
	Self Destruct Timer [Float]
	Has Self Destruct [Bool]
Body <- ModelBody <- DynamicBody <- Ship

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] SHIP
Ship::Save
	DynamicBody::Save
		ModelBody::Save
			Body::Save
				Properties [String]
				Index for Frame [Int32]
				Label [String]
				Dead? [Bool]
				Position [Vector3d] (3 Doubles)
				Orientation [Double] (9 of these – 3x3 matrix)
				Phys Radius [Double]
				ClipRadius [Double]
			IsStatic [Bool]
			Colliding [Bool]
			Model Name [String]
			Model
				SaveVisitor?
				Animation (multiple)
					Animation Progress [Double]
				Cur Pattern Index [Int32]
			Shields
				Enabled [Bool]
				Size [Int32]
				Shield (multiple)
					ColorR [Byte]
					ColorG [Byte]
					ColorB [Byte]
					Name [String]
		Force [Vector3d]
		Torque [Vector3d]
		Vel [Vector3d]
		AngVel [Vector3d]
		Mass [Double]
		Mass Radius [Double]
		Ang Inertia [Double]
		IsMoving [Bool]
	Skin
		Color1R [Byte]
		Color1G [Byte]
		Color1B [Byte]
		Color2R [Byte]
		Color2G [Byte]
		Color2B [Byte]
		Color3R [Byte]
		Color3G [Byte]
		Color3B [Byte]
		Decals (multiple)
			Decal [String]
		Label [String]
	Ang Thrusters [Vector3d]
	Thrusters [Vector3d]
	Wheel Transition [Int32]
	Wheel State [Float]
	Launch Lock Timeout [Float]
	Test Landed [Bool]
	Flight State [Int32]
	Alert State [Int32]
	Last Firing Alert [Double]
	Hyperspace Destination
		Sector X [Int32]
		Sector Y [Int32]
		Sector Z [Int32]
		System Index [Int32]
		Body Index [Int32]
	Hyperspace Countdown [Float]
	Gunmounts (multiple)
		State [Int32]
		Recharge [Float]
		Temperature [Float]
	ECM Recharge [Float]
	Ship ID [String]
	Docked with Port [Int32]
	Index for Body Docked With [Int32]
	Hull Mass Left []Float
	Shield Mass Left [Float]
	Shield Cool Down [Float]
	if(curAICmd)
		1 [Int32]
		Cmd Name [Int32]
		Index for Body [Int32]
		if(child)
			Recursive serialization of AICommand
		else
			CMD_NONE [Int32]
	else
		0 [Int32]
	AI Message [Int32]
	Thruster Fuel [Double]
	Reserve Fuel [Double]
	Controller Type [Int32]
	Controller
		Flight Control State [Int32]
		Set Speed [Double]
		Low Thrust Power [Float]
		Rotation Damping [Bool]
		Index for Body Combat Target [Int32]
		Index for Body Nav Target [Int32]
		Index for Body Set Speed Target [Int32]
	Navlights
		Time [Float]
		Enabled [Bool]
		Color [Byte] (Unknown number of these)
Body <- ModelBody <- DynamicBody <- Ship <- Missile

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] MISSILE
Missile::Save
	Ship::Save
		DynamicBody::Save
			ModelBody::Save
				Body::Save
					Properties [String]
					Index for Frame [Int32]
					Label [String]
					Dead? [Bool]
					Position [Vector3d] (3 Doubles)
					Orientation [Double] (9 of these – 3x3 matrix)
					Phys Radius [Double]
					ClipRadius [Double]
				IsStatic [Bool]
				Colliding [Bool]
				Model Name [String]
				Model
					SaveVisitor?
					Animation (multiple)
						Animation Progress [Double]
					Cur Pattern Index [Int32]
				Shields
					Enabled [Bool]
					Size [Int32]
					Shield (multiple)
						ColorR [Byte]
						ColorG [Byte]
						ColorB [Byte]
						Name [String]
			Force [Vector3d]
			Torque [Vector3d]
			Vel [Vector3d]
			AngVel [Vector3d]
			Mass [Double]
			Mass Radius [Double]
			Ang Inertia [Double]
			IsMoving [Bool]
		Skin
			Color1R [Byte]
			Color1G [Byte]
			Color1B [Byte]
			Color2R [Byte]
			Color2G [Byte]
			Color2B [Byte]
			Color3R [Byte]
			Color3G [Byte]
			Color3B [Byte]
			Decals (multiple)
				Decal [String]
			Label [String]
		Ang Thrusters [Vector3d]
		Thrusters [Vector3d]
		Wheel Transition [Int32]
		Wheel State [Float]
		Launch Lock Timeout [Float]
		Test Landed [Bool]
		Flight State [Int32]
		Alert State [Int32]
		Last Firing Alert [Double]
		Hyperspace Destination
			Sector X [Int32]
			Sector Y [Int32]
			Sector Z [Int32]
			System Index [Int32]
			Body Index [Int32]
		Hyperspace Countdown [Float]
		Gunmounts (multiple)
			State [Int32]
			Recharge [Float]
			Temperature [Float]
		ECM Recharge [Float]
		Ship ID [String]
		Docked with Port [Int32]
		Index for Body Docked With [Int32]
		Hull Mass Left []Float
		Shield Mass Left [Float]
		Shield Cool Down [Float]
		if(curAICmd)
			1 [Int32]
			Cmd Name [Int32]
			Index for Body [Int32]
			if(child)
				Recursive serialization of AICommand
			else
				CMD_NONE [Int32]
		else
			0 [Int32]
		AI Message [Int32]
		Thruster Fuel [Double]
		Reserve Fuel [Double]
		Controller Type [Int32]
		Controller
			Flight Control State [Int32]
			Set Speed [Double]
			Low Thrust Power [Float]
			Rotation Damping [Bool]
			Index for Body Combat Target [Int32]
			Index for Body Nav Target [Int32]
			Index for Body Set Speed Target [Int32]
		Navlights
			Time [Float]
			Enabled [Bool]
			Color [Byte] (Unknown number of these)
	Index for Body Owner [Int32]
	Power [Int32]
	Armed [Bool]
Body <- ModelBody <- DynamicBody <- Ship <- Player

Code: Select all

Section Label [String] "Body"
Type of Body [Int32] PLAYER
Player::Save
	Ship::Save
		DynamicBody::Save
			ModelBody::Save
				Body::Save
					Properties [String]
					Index for Frame [Int32]
					Label [String]
					Dead? [Bool]
					Position [Vector3d] (3 Doubles)
					Orientation [Double] (9 of these – 3x3 matrix)
					Phys Radius [Double]
					ClipRadius [Double]
				IsStatic [Bool]
				Colliding [Bool]
				Model Name [String]
				Model
					SaveVisitor?
					Animation (multiple)
						Animation Progress [Double]
					Cur Pattern Index [Int32]
				Shields
					Enabled [Bool]
					Size [Int32]
					Shield (multiple)
						ColorR [Byte]
						ColorG [Byte]
						ColorB [Byte]
						Name [String]
			Force [Vector3d]
			Torque [Vector3d]
			Vel [Vector3d]
			AngVel [Vector3d]
			Mass [Double]
			Mass Radius [Double]
			Ang Inertia [Double]
			IsMoving [Bool]
		Skin
			Color1R [Byte]
			Color1G [Byte]
			Color1B [Byte]
			Color2R [Byte]
			Color2G [Byte]
			Color2B [Byte]
			Color3R [Byte]
			Color3G [Byte]
			Color3B [Byte]
			Decals (multiple)
				Decal [String]
			Label [String]
		Ang Thrusters [Vector3d]
		Thrusters [Vector3d]
		Wheel Transition [Int32]
		Wheel State [Float]
		Launch Lock Timeout [Float]
		Test Landed [Bool]
		Flight State [Int32]
		Alert State [Int32]
		Last Firing Alert [Double]
		Hyperspace Destination
			Sector X [Int32]
			Sector Y [Int32]
			Sector Z [Int32]
			System Index [Int32]
			Body Index [Int32]
		Hyperspace Countdown [Float]
		Gunmounts (multiple)
			State [Int32]
			Recharge [Float]
			Temperature [Float]
		ECM Recharge [Float]
		Ship ID [String]
		Docked with Port [Int32]
		Index for Body Docked With [Int32]
		Hull Mass Left []Float
		Shield Mass Left [Float]
		Shield Cool Down [Float]
		if(curAICmd)
			1 [Int32]
			Cmd Name [Int32]
			Index for Body [Int32]
			if(child)
				Recursive serialization of AICommand
			else
				CMD_NONE [Int32]
		else
			0 [Int32]
		AI Message [Int32]
		Thruster Fuel [Double]
		Reserve Fuel [Double]
		Controller Type [Int32]
		Controller
			Flight Control State [Int32]
			Set Speed [Double]
			Low Thrust Power [Float]
			Rotation Damping [Bool]
			Index for Body Combat Target [Int32]
			Index for Body Nav Target [Int32]
			Index for Body Set Speed Target [Int32]
		Navlights
			Time [Float]
			Enabled [Bool]
			Color [Byte] (Unknown number of these)
impaktor
Posts: 1029
Joined: Fri Dec 20, 2013 9:54 am
Location: Tellus
Contact:

Re: Thanks to the developers! (& suggestion for savegames)

Post by impaktor »

Really awesome to see you're still working on this!

Until you get an answer by more knowledgeable people, I can at least say that you definitely want to do it in JSON, since that is the format we already use for language, (and here: #3252 is code that moves ships and station definitions to json), so we already have code for parsing Json files.

And, as mentioned in a previous post here, the work that had started/stopped for moving saves to Json is here:
github.com/robn/json-savefile and I think looking at that, or even using that and finish it is bound to be a good source of learning.
jpab
Posts: 77
Joined: Thu Jul 18, 2013 12:30 pm
Location: UK

Re: Thanks to the developers! (& suggestion for savegames)

Post by jpab »

Really awesome to see you're still working on this!
+1! This is a really useful (and difficult!) thing to work on.
We need a savegame format that is a tree, the ability to navigate nodes, return the number of child nodes, iterate through the nodes etc. There are two obvious choices: XML and JSON. I'm favoring JSON, because its easier to read - what do you think? I believe either can be platform independent.
Yes, definitely JSON since we already use it in other places, with some data that is currently stored in the form of Lua scripts being converted to JSON (we don't currently use XML anywhere).
The new savegame system will need some basic functions written for node navigation, and reading and writing the various data types (relatively painless - barring the "auto" type, but will cross that bridge when come to it).
Most of the low level (non-domain-specific) node navigation code and handling the raw value types (numbers, strings, arrays etc) should already be provided by the JSON parsing library that we use, jsoncpp. We have a copy of the code for that library in the contrib/json/ directory of the repository... I don't think we've modified it at all (and I would recommend against modifying it without a really strong reason), though it may not be the latest version of the library. You'll probably need to write helper functions to serialise 3D vectors, colour values and perhaps some other basic value types, since JSON itself only supports string/number/boolean/null for basic values (plus array and "object" for structures).

I'm not sure what you mean by the "auto" type... are you referring to the C++11 'auto' keyword(*)? That 'auto' is not itself a type, it tells the compiler to deduce the type automatically.

(* auto was a keyword in C++ prior to C++11, but it had a different meaning and was almost never used)
I've examined the code enough to implement a node-based structure of the existing save data - is this what you have in mind?
That's probably the right place to start. Long term, the major reason for changing the save format is to make it easier to improve the game without breaking save files, and doing that effectively may need some changes to the tree structure of the format, not just a switch to JSON.

The current format relies very strongly on having an exact match between the version of the save code that wrote the save file and the version of the code that is reading the file. For example, saving an extra data field for a particular object type will shift the offsets of all subsequent saved fields and objects, which breaks compatibility between different versions of the loading code. Switching to JSON will mean that changes of that kind can be made in a backward-compatible way (older saves will be missing the field but can use a default value). However, that level of compatibility is quite low level -- robust behavioural compatibility is harder to achieve and will probably have to be handled on a case-by-case basis as we continue to develop the game.
The structure of a samegame file will be essentially the same as the existing one, but written in a hierarchical tree structure (nodes containing data, nested inside other nodes etc). Each node type will have a name.
Yes, and probably. JSON doesn't have a built-in structure for named object types, but as you are designing the save format you can specify some convention to do this, like including a string 'type' field within each object. However, I think I might be misunderstanding what you mean by "Each node type will have a name".
Saving the number of objects (as int32) before saving the objects will no longer be required, because we can call the "get number of nodes function", and/or just iterate through the objects. The tree will be quite deep.
Yes, and yes.
Future savegame formats will have new node types. When loading an older file, the new version code should create a default/nominal value (e.g. when looking for a node "colour of crew hats" that did not exist in the old savegame file version).
Yes.
So it would seem that the remaining tasks before coding, are to learn JSON and pick a JSON parser.
Yes, you will need to learn JSON (it's very simple). You don't need to pick a JSON parser -- as I mentioned above, we already use jsoncpp.
However, I do feel a bit out of my depth, what with work commitments and my other software project (a computer algebra system). I can't say when I'll get this task completed I'm afraid. I'll probably need a bit of help with some unfamilliar aspects of software development.
Don't worry -- we all have other commitments too, so we totally understand that it can take a long time to make progress on something like this. I'm happy to try to help answer any questions you have, although I may be very slow to reply sometimes due to my own time constraints. I'm sure others will be happy to help too.
Following on from the [existing] savegame process pseudocode (see 3 posts above) the savegame process for all the "body" types in Pioneer is shown below:
... full save tree description elided ...
I haven't read through the entire tree in detail yet, but a few things jump out at me:
  1. You have various 'Type of X' fields listed as [Int32]. These should use a string (the name of the type) rather than a number. We have some code already to deal with converting between enum values and strings, which you should be able to use for this purpose (and any other time that you want to save an enum value). Please ask if you have difficulty finding it or working out how to use it.
  2. Orientation matrices. I would probably store these as quaternions (4 numbers) instead of a matrix representation (9 numbers), purely because the quaternion is a more compact representation. This is a minor detail though.
  3. Why is the 'Properties' field of a 'Body' a string? It seems like that should be a JSON object (ie, key/value pairs).
  4. You have PhysRadius and ClipRadius stored for the Body type. These are currently saved, but I'm not sure that they should be saved. I think these values always come from somewhere else anyway (e.g., for a ModelBody, these values should come from the model data). There are probably other fields in the data that are like that -- values which actually come from some other static data (or from procedurally generated static data, like the PhysRadius and ClipRadius of procedurally generated planets). The values are copied into fields in the Body class so that they can be accessed quickly and uniformly by other code. Saving them makes it easy to recreate the object, but it's bad for robustness in the face of other changes: for example, the model data itself is not stored in the save game (and shouldn't be) -- if a ship design is changed then its ClipRadius or PhysRadius might change, but with the current system those changes might not be applied to ships that are loaded from save games, since the radius values are stored directly in the save. That could lead to weird behaviour, like ships vanishing or collisions being ignored because the clip/phys radius value for a particular object doesn't match the actual model that's being displayed. This is an example of the kind of backward compatibility problem that won't be solved simply by converting to JSON, but which requires more careful thought to avoid. Unfortunately, I suspect that there are a lot of potential pitfalls like this that will make old saves break in subtle ways.
Finally, as impaktor said, it would be a good idea to look at robn's json-savefile branch and perhaps use it as a starting point for this work.
robn
Posts: 302
Joined: Mon Jul 01, 2013 1:11 am
Location: Melbourne, Australia

Re: Thanks to the developers! (& suggestion for savegames)

Post by robn »

jpab wrote:Finally, as impaktor said, it would be a good idea to look at robn's json-savefile branch and perhaps use it as a starting point for this work.
Feel free to ask me questions about this. Its not fresh in my head (I haven't been very active on Pioneer for quote some time), but I did have a plan :)
nick
Posts: 85
Joined: Mon Sep 08, 2014 9:24 pm
Location: Plymouth, UK

Re: Thanks to the developers! (& suggestion for savegames)

Post by nick »

Thank you all for your replies :)

I did suspect that some restructuring of the savegame process is needed, in addition to moving to a node-tree structure, but that can be a future task.

JSON it is, and good to know that the required JSON node functions already exist.

By "Each node type will have a name", I mean that client code can for example ask "do we have a sub-node called 'Ship for Sale'?" and how many of them?

The pseudo-code I've posted above is for the existing savegame system.

impaktor - will have a look through robn's branch when I get the chance.

jpab - you've posed some very good questions:

(1) Enums (as int32) should actually be saved as strings.
(2) Use quarternians instead of matrices.
(3) Properties string should be split into keys/values.
(4) PhysRadius, ClipRadius and other data probably shouldn't be saved with their objects.

(1) No problem - especially if the conversion functions exist.
(2) Not a problem, but I think I'll deal with that later, so for this task I can focus on the migration to tree structure.
(3) Saving as a string for now will be easy to do, but of course will need to be split into key/value pairs at some point.
(4) A bit beyond me! I'll have to save it as it is for now.

robn - thank you. I'm sure I'll have some questions when I get down to coding. Plan is to move existing structure to JSON tree, and deal with other issues for next task.

Thanks everyone.
Post Reply