Tips and Tricks
Let me tell you what I did wrong - so you don't have to
Case sensitivity
"Player" ≠ "player"
Normalize keys.
Enum.values()
values() creates every time a new array.
Cache it.
Even better: use maps instead of iterating (O(1)).
public static final Map<Integer, MyEnum> BY_ID = new HashMap<>();
static {
for (MyEnum enumValue : VALUES) {
BY_ID.put(enumValue.getId(), enumValue);
}
}
Chunk loading side effects
Some methods will load chunks implicitly. This can cause unexpected lag.
Loads chunk
Location#getChunk()World#getChunkAt(x, z)World#getChunkAt(Block)World#getChunkAt(Location)Location#getBlock()
No chunk loading
World#isChunkLoaded(x, z)
Many API calls are not "read-only" - they trigger chunk loads.
Storing entities directly
Don’t store entities as objects (e.g. LivingEntity, Skeleton) in maps. Breaks as soon as the chunk unloads.
Better
Store identifiers instead.
Access later
Before using:
- check if entity exists
- check if the chunk is loaded
Entity references are not stable.
Player-based rendering
Don’t simulate everything globally. React to what the player actually sees (packets).
Example: Disco Fish\ → only track & tick spawned entities
Deeper dive: [[Disco Fish System|Monty's-Book/Disco-Fish-System]]