I’ve been trying to develop a 2D MMORPG (like tibia :P) using Java. The server of my game loads all the map and store all the objects (tiles, itens, player, monster) in memory. But when I try to load a map very big, it consume all the memory of my computer :(, the question is: what is the best way to load a big map and handle with the objects?
In my opinion you did something horrible wrong, because I can’t imagine a game world which would consume too much memory on the server (did you try to extend the Java heap?)
The map I’m trying to load is the global Tibia map, so it is very big! Maybe the problem is the structure of my objects. :clue: Is there any best practices to struct this kind of objects?
I don’t know how big this map is, but most of the time the final data-structure isn’t the problem. It may be that your parser creates too many temporary object which let the JVM explode.
Anyway, did you try to just extend the Java heap size?(add -Xmx1024m as a start parameter to Java to set the heap to 1GB)
Yes Danny02, I setted -Xmx3048m -XX:MaxPermSize=2048m and it consumes all the memory. The map has thereabout 13437971 tiles, with at least one item (the ground), it’s a lot of objects :-X kkk
Then pls show us some code. What are your data-structures and how do you load the map, because when we say you just need one id + type per tile you should only need around 200mb
One tip - don’t make objects for each tile, use arrays of primitives + objects for special properties of tiles (if any) instead. If your world will expand or/and take very big amounts of RAM, consider storing it in chunks and load them when someone is close to them or you must update something.
When you have an MMO, why do you send the complete Map to each client?
Only send each client the dynamic objects (changed delta data) in the clients relevant “area”.
Static Leveldata, like hills, trees etc (everything that cant change) should be locally in the clients resources at the start.
If you need to change the map, offer patches or a downloader to the clients.
These changes can remain on a standard file-webserver.
if you meant, that you server-side map, (needed for the gamelogic) is too big,
then you made a structural error on how much data your serverside map actually needs.
It (the mapdata representing the world) only needs relevant data for collision detection, events and dynamic objects. This should be quite compact in
the size of this should be only few megabytes when you handle your data efficiently.
Damocles, I’m sending to client only the relevant part of the map, only what the player can see. The problem maybe is the structure of my object on the server-side. Follow the structure of them:
public class Mapa extends AbstractMap { //AbstractMap there are only methods
protected HashMap<Position, Tile> tiles = new HashMap<Position, Tile>();
}
public class Tile {
private final Position position;
private Item ground;
private final Mapa mapa; //there is only one instance of Mapa on server
private List<Item> itens = new LinkedList<Item>();
private List<Creature> creatures = new LinkedList<Creature>(); //I'm not loading creatures in the map load...
}
public class Position {
private int x;
private int y;
private int z;
}
public class Item {
private ItemType itemType;
}
public class ItemType {
protected Group group; //it's an Enum
protected EnumSet<ItemAttribute> attributes;
protected int serverId;
protected int clientId;
protected String article;
protected String name;
protected String pluralName;
}
Yeah, in this case you might want to find a new way to represent a map. You are creating about 5 new objects per tile. Eventually, you’ll run out of room.
For large maps use primitives like int or byte. They are easier to store and you can fit a lot more without crashing. It really helps to separate the items from the map. Any object on the tile should probably be stored in a (item, x position, y position) to help reduce space. The smaller the better when it comes to any large map.
All of the above is correct, and I also recommend looking into a static tile system so you only create one instance of a tile, and draw it in multiple places. And really ask yourself, does the tile need to know its position? I’ve never created a tile system where the tile knows its position in the world, and it works out pretty well because all you need is a array of the tiles, and then a way to get a tile out of the array. That’s instantly much less memory used, and you conserve the intended functuality!
Edit: I just noticed you’re storing your map in each tile. Why do this? If you need the world, just pass it in when you need it. Storing the map just seems wasteful!
A strategy I have used before is only Loading the tiles within your clients player position and that usually works quite well as it won’t load other clients tiles and will run very smoothly