Minecraft style infinity blocky world ( fopen and holding blocks in ram )

Started by
8 comments, last by alh420 9 years, 4 months ago
Hello everyone!
First we will have:

struct item {
unsigned short type;
unsigned int age;
float pos[3];
};
 
struct block {
unsigned short type;
unsigned int age;
int flags;
};
 
struct chunk {
item *items; // items count is always changing
block blocks[2048]
};
My wish is to have infinity world like in minecraft but instead of chunks crowing only x,y side my wish is that it will also grow in z side so there will be no limits that how deep you can go.
First question will be that how should i hold chunks?
i can make like:

chunk ***chunks_negativeside
chunk ***chunks_positiveside
but the problem will be that when i wish to clean up those far away chunks where i were, things got complicated.
( perhaps just hold them without order at first, then sort them and when clear up is needed, short them again... )
Its nice when i know easily the order that what chunk is what so i could example be in chunk x0,y0,z0 and find x1,y0,z0 fast or find chunk x0,y12,z5
( without need of looping evey chuck to find to correct one )
Now, that was the first thing i need help, after this is understandable for me
i wish to know how to read/write file that way that i don't read all chunks at once. I wish to keep everything inside of one file.
The thing what makes it complicated is that x,y,z can be -9999 or 9999
how to short them or put them into file?
Also, as you can see that each chunk have items and there can be infinity amount of items in one chunk.
Items may also have data what can grow infinitely
( or blocks, chunks )
So while saving the file, i want it somehow not to save everything but update things somehow...
Can somehow please help me clear things up and guide me?
Thank you!
Advertisement

How about using some sectoring scheme and keeping a certain (maybe constant) amount of sectors in the RAM simultaneously. You can define that each sector has like 64x64x64 blocks (or maybe more/less ?) and you keep (maybe) 16x16x16 sectors in the memory. So when starting the game or moving in the world you can populate the sector data based on the camera location. Maybe you can use some sort of spatial hashing (ie. a key value based on the sector position) in order to seek and load the correct sector easily from the map database.

How you manage the sectors is up to you, maybe you can rotate the sector array when the camera moves (ie. shift the sectors based on the camera movement and if the sector is at edge it will be discarded - and new sectors appearing will need to be refreshed).

Cheers!

Alright but how about saving/reading file part?
Can someone explain how to do what i wish.

http://www.cplusplus.com/reference/cstdio/fopen/?kw=fopen
http://www.cplusplus.com/reference/cstdio/fread/?kw=fread
http://www.cplusplus.com/reference/cstdio/fclose/?kw=fclose

These links should help. The names of the functions are fairly self-explanatory, so I don't think I need to explain them.

http://www.cplusplus.com/articles/oyhv0pDG/

That article will also be of help. It uses C++ streams (I'm assuming you're using C, not C++, based on you wanting to use fopen, which is a C function), but it should be trivial to convert it to using C standard IO functions.

I'm using c++, I'm kinda new in writing files.
Well i know how to work with fopen( "", "rb", f ), fopen( "", "wb", f )

but i need something far more advanced than that


	struct item {
	unsigned short type;
	unsigned int age;
	float pos[3];
	char *cdata; // item data can increase/decrease
	};
 
	struct block {
	unsigned short type;
	unsigned int age;
	int flags;
	};
 
	struct chunk {
	item *items; // items count is always changing
	block blocks[2048];
	};

	chunk myworld[3];
	myworld[0].items = new item[2];
	myworld[0].items[0].cdata = new char[4];
	myworld[0].items[1].cdata = new char[16];

	myworld[1].items = new item[1];
	myworld[1].items[0].cdata = new char[8];

	myworld[2].items = new item[4];
	myworld[2].items[0].cdata = new char[4];
	myworld[2].items[1].cdata = new char[4];
	myworld[2].items[2].cdata = new char[16];
	myworld[2].items[3].cdata = new char[8];
	// now i need to save myworld[3] to file
	delete myworld[1].items;
	myworld[1].items = new item[3]; // as you can see, now items count is increased, it can decrease as well.
	myworld[1].items[0].cdata = new char[32];
	myworld[1].items[1].cdata = new char[8];
	myworld[1].items[2].cdata = new char[4];
	// now i need to update file somehow so i wont be writing the whole file again
	// and while reading it i must find easily each item in chunk
	// this is the problem, when i change the size of item in block i have to push data what
	// is below that forward to make room and also when i decrease the items size them move whole data back
	// this is really slow protsess, the game is doing this all the time so it need to be as fast as possible
	// also the myworld[x] x size changes, only increases

	// I know that in hard drive, the data is not organized ( not in right order )
	// i guess there are pointers what point to data like in ram
	// because if you increase the file size, it would be damn slow to push the whole hard drive data forward...





I could keep thing simple and create new file for each chunk so items will added to the end of file so they can easily increase or decrease but thats terrible.

Game would be having like 100k files and that would mean that computer will turn slow since the data on hard drive is just too messy.

So my question is that, should i play with fwrite/fread and have a huge cpu usable or is there anything meant for what i am trying to do now.
Thanks!

Well, if you're using C++ then you should be using fstream, and not fopen.

I'm sure that you won't be inserting new chunks into the middle of the map, only appending them to the end when generating them.

Just open the file for reading and writing operations, and when you generate a new chunk, just append it to the end of the file.

But the problem is that each chunks contains x amount of items and items have x amount of data in them.

How i would update item count on chunk then?

Writing variable size arrays/vector/whatever:

- write size (uint)

- write array elements

Reading:

- read size

- allocate array of said size

- read array elements

For hierarchies it's probably a good idea to flatten them first (and also write parent relation, i.e. an index).

I readed online and found out that what i seek doesn't exist at all. Hmm this ... is going to give me alot of headache since it is really complicated to update large file ( 10-300mb )
I guess i just have to use more than 1 files.

One way could be using a database to store the data.

You could have a table with the chunks as binary blobs, load and save them as needed, and let the database software handle the details of streaming it to/from file.

sqlite is free and fairly simple to use, though it is not very advanced.

better software have more advance caching schemes, making them faster and more efficient, but are a lot more work to set up.

sqlite could be a good starting point, it works on a single file with no setup needed.

This topic is closed to new replies.

Advertisement