|
| 1 | +# Data-oriented interfaces |
| 2 | + |
| 3 | +`AUTHOR: Idra` |
| 4 | +`HAS CONTEXT: Idra, Seggan` |
| 5 | + |
| 6 | +## What the hell is that? I'm scared |
| 7 | + |
| 8 | +Ok 'data-oriented interfaces' sounds really intimidating but I promise it's not. Basically, we much prefer to use interfaces instead of classes because we can inherit from multiple interfaces (well, there are some other reasons too but nevermind that). The problem is of course that interfaces can't have fields. |
| 9 | + |
| 10 | +So traditionally, we might solve that like this. Imagine we have want to store the block's direction, like in `PylonDirectionalBlock`. We might do this: |
| 11 | + |
| 12 | +```kotlin |
| 13 | +interface PylonDirectionalBlock { |
| 14 | + val facing |
| 15 | +} |
| 16 | +``` |
| 17 | + |
| 18 | +Now we've forced the block to handle this for us. But think about it. This is really annoying because the block has to now also handle all the loading/unloading logic (it has to write the direction in `write` and then load it again in the load constructor). Which is a lot of extra code if we start doing this for lots of interfaces. |
| 19 | + |
| 20 | +## How do we solve that then? |
| 21 | + |
| 22 | +What we're going to do is just have a map which stores the face of each `PylonDirectionalBlock`, like this: |
| 23 | + |
| 24 | +```kotlin |
| 25 | +interface PylonDirectionalBlock { |
| 26 | + var facing: BlockFace |
| 27 | + get() = directionalBlocks[this] ?: error("No direction was set for block $key") |
| 28 | + set(value) { |
| 29 | + directionalBlocks[this] = value |
| 30 | + } |
| 31 | + |
| 32 | + companion object { |
| 33 | + private val directionalBlocks = IdentityHashMap<PylonDirectionalBlock, BlockFace>() |
| 34 | + } |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +One other thing, we need to make sure that we store and load the direction at the same time as the block: |
| 39 | + |
| 40 | +```kotlin |
| 41 | +@EventHandler |
| 42 | +private fun onDeserialize(event: PylonBlockDeserializeEvent) { |
| 43 | + val block = event.pylonBlock |
| 44 | + if (block is PylonDirectionalBlock) { |
| 45 | + directionalBlocks[block] = event.pdc.get(directionalBlockKey, PylonSerializers.BLOCK_FACE) |
| 46 | + ?: error("Direction not found for ${block.key}") |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +@EventHandler |
| 51 | +private fun onSerialize(event: PylonBlockSerializeEvent) { |
| 52 | + val block = event.pylonBlock |
| 53 | + if (block is PylonDirectionalBlock) { |
| 54 | + event.pdc.set(directionalBlockKey, PylonSerializers.BLOCK_FACE, directionalBlocks[block]!!) |
| 55 | + } |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +That's basically it. |
0 commit comments