2

I have been writing a Minecraft replica for OpenGL practice (as many do I guess), however after writing the basic rendering API I noticed the real Minecraft uses a lot or memory - around 800MB! I can fully understand why this is with all the blocks it has to remember along with mobs and probably terrain data for the generator...I asked myself "This block is exactly the same as that block..can they be in the code?" and remembered C++ has pointers, so I have attempted to do the same in Java the only way I could think of, creating one static instance of each block and not using the new keyword, is this the best way? It definitely seems to help..I would still like it to be better if that is possible?
Here is the class in question..

public abstract class Block {
    public static DirtBlock Dirt = new DirtBlock();
    public static GrassBlock Grass = new GrassBlock();
    public static RedstoneOreBlock RedstoneOre = new RedstoneOreBlock();
    public static TNTBlock TNT = new TNTBlock();
    public static MonsterSpawnerBlock Monserspawner = new MonsterSpawnerBlock();
    public static BedrockBlock Bedrock = new BedrockBlock();
    public static StoneBlock Stone = new StoneBlock();
    public static GlassBlock Glass = new GlassBlock();
    public static SandBlock Sand = new SandBlock();
    public static WaterBlock Water = new WaterBlock();
    public static SnowBlock Snow = new SnowBlock();
    public static SnowGrassBlock SnowyGrass = new SnowGrassBlock();
    public static IceBlock Ice  = new IceBlock();
    public static CoalBlock Coal = new CoalBlock();

Current memory usage is about 200MB for a 100 chunk world with each chunk made up of 16 blocks wide by 64 high and 16 deep, 1,638,400 blocks total - about 128 bytes per block.

Lee Fogg
  • 775
  • 6
  • 22
  • You can reduce it even more by storing only a one-byte (or even smaller!) block-ID, which indexes into an array or something. Also, more importnatly, by not storing every chunk in memory at a time. – BlueRaja - Danny Pflughoeft Jun 18 '13 at 01:51
  • I am using a block id for each type of block which is a byte, but it's mainly for quickly knowing what type of block any is without using instanceof. How would i go about not storing every chunk? I'll be implementing a world loader which i will use as a live chunk loader/saver... – Lee Fogg Jun 18 '13 at 14:35
  • *"I am using a block id for each type of block.."* - I meant that each chunk is a large array of ID's, rather than a large array of objects. *"How would i go about not storing every chunk?"* - You store the chunks in a file, and only load the ones nearest you into memory (and unload them when you move away). This is what Minecraft does, and is the whole reason for breaking the world into chunks to begin with *(well, that and so you don't need to download the entire world to play on a multiplayer server)* – BlueRaja - Danny Pflughoeft Jun 18 '13 at 15:45
  • 1
    Yes I did say I am going to write a save/loader and yeah I know thats how minecraft works. I will try to replace my array of pointers with IDs and let you know if there's a improvement. – Lee Fogg Jun 18 '13 at 21:50

1 Answers1

1

Yes, this is a good way. It is called Flyweight pattern. But instead of static fields consider using factory of objects. This will make your code more testable in the long run.

In computer programming, flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory. Often some parts of the object state can be shared, and it is common practice to hold them in external data structures and pass them to the flyweight objects temporarily when they are used.

A classic example usage of the flyweight pattern is the data structures for graphical representation of characters in a word processor. It might be desirable to have, for each character in a document, a glyph object containing its font outline, font metrics, and other formatting data, but this would amount to hundreds or thousands of bytes for each character. Instead, for every character there might be a reference to a flyweight glyph object shared by every instance of the same character in the document; only the position of each character (in the document and/or the page) would need to be stored internally.

From Wikipedia, http://en.wikipedia.org/wiki/Flyweight_pattern

Community
  • 1
  • 1
Grzegorz Żur
  • 47,257
  • 14
  • 109
  • 105
  • Thanks, now I know the name of it and that it's in good practice, flyweight sounds exactly the same as what i'm doing. Could you elaborate on what a "factory of objects" is please? – Lee Fogg Jun 17 '13 at 20:37
  • Factory is simply speaking an object (method or function) that creates all instances of a particular class. In other words, a replacement for `new` or the only place where `new Block()` is used. This is concept http://en.wikipedia.org/wiki/Factory_%28software_concept%29 that has few patterns implementing this: factory method, abstract factory, builder. – Grzegorz Żur Jun 17 '13 at 21:20
  • Ah thanks, Seems i'm using them too..for my texture and sound loaders, only has a init to load them all and a play/bind for each instance. :D – Lee Fogg Jun 17 '13 at 21:57