Skip to content

Commit 9986a6f

Browse files
author
Adam Arold
committed
Add entity actions
1 parent 3779a0e commit 9986a6f

13 files changed

Lines changed: 151 additions & 10 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.hexworks.cavesofzircon.attributes
2+
3+
import org.hexworks.amethyst.api.Attribute
4+
import org.hexworks.amethyst.api.entity.EntityType
5+
import org.hexworks.cavesofzircon.commands.EntityAction
6+
import org.hexworks.cavesofzircon.extensions.GameEntity
7+
import org.hexworks.cavesofzircon.world.GameContext
8+
import kotlin.reflect.KClass
9+
10+
11+
class EntityActions(private vararg val actions: KClass<out EntityAction<out EntityType, out EntityType>>)
12+
: Attribute {
13+
14+
fun createActionsFor(context: GameContext, source: GameEntity<EntityType>, target: GameEntity<EntityType>):
15+
Iterable<EntityAction<out EntityType, out EntityType>> {
16+
return actions.map {
17+
try {
18+
it.constructors.first().call(context, source, target)
19+
} catch (e: Exception) {
20+
throw IllegalArgumentException("Can't create EntityAction. Does it have the proper constructor?")
21+
}
22+
}
23+
}
24+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.hexworks.cavesofzircon.attributes.flags
2+
3+
import org.hexworks.amethyst.api.Attribute
4+
5+
object BlockOccupier : Attribute

src/main/kotlin/org/hexworks/cavesofzircon/attributes/types/EntityTypes.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ import org.hexworks.amethyst.api.base.BaseEntityType
44

55
object Player : BaseEntityType(
66
name = "player")
7+
8+
object Wall : BaseEntityType(
9+
name = "wall")

src/main/kotlin/org/hexworks/cavesofzircon/blocks/GameBlock.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package org.hexworks.cavesofzircon.blocks
33
import org.hexworks.amethyst.api.entity.EntityType
44
import org.hexworks.cavesofzircon.builders.GameTileRepository
55
import org.hexworks.cavesofzircon.extensions.GameEntity
6+
import org.hexworks.cavesofzircon.extensions.occupiesBlock
67
import org.hexworks.cavesofzircon.extensions.tile
8+
import org.hexworks.cobalt.datatypes.Maybe
79
import org.hexworks.zircon.api.data.BlockSide
810
import org.hexworks.zircon.api.data.Tile
911
import org.hexworks.zircon.api.data.base.BlockBase
@@ -19,6 +21,12 @@ class GameBlock(private var defaultTile: Tile = GameTileRepository.FLOOR,
1921
val isWall: Boolean
2022
get() = defaultTile == GameTileRepository.WALL
2123

24+
val isOccupied: Boolean
25+
get() = occupier.isPresent
26+
27+
val occupier: Maybe<GameEntity<EntityType>>
28+
get() = Maybe.ofNullable(currentEntities.firstOrNull { it.occupiesBlock })
29+
2230
val isEmptyFloor: Boolean
2331
get() = currentEntities.isEmpty()
2432

@@ -47,4 +55,10 @@ class GameBlock(private var defaultTile: Tile = GameTileRepository.FLOOR,
4755
override fun fetchSide(side: BlockSide): Tile {
4856
return GameTileRepository.EMPTY
4957
}
58+
59+
companion object {
60+
61+
fun createWith(entity: GameEntity<EntityType>) = GameBlock(
62+
currentEntities = mutableListOf(entity))
63+
}
5064
}

src/main/kotlin/org/hexworks/cavesofzircon/builders/EntityFactory.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,32 @@ import org.hexworks.cavesofzircon.systems.CameraMover
1010
import org.hexworks.cavesofzircon.systems.InputReceiver
1111
import org.hexworks.cavesofzircon.systems.Movable
1212
import org.hexworks.cavesofzircon.world.GameContext
13+
import org.hexworks.cavesofzircon.attributes.flags.BlockOccupier
14+
import org.hexworks.cavesofzircon.attributes.types.Wall
15+
import org.hexworks.cavesofzircon.attributes.EntityActions
16+
import org.hexworks.cavesofzircon.commands.Dig
17+
import org.hexworks.cavesofzircon.systems.Diggable
1318

1419
fun <T : EntityType> newGameEntityOfType(type: T, init: EntityBuilder<T, GameContext>.() -> Unit) =
1520
Entities.newEntityOfType(type, init)
1621

1722
object EntityFactory {
1823

1924
fun newPlayer() = newGameEntityOfType(Player) {
20-
attributes(EntityPosition(), EntityTile(GameTileRepository.PLAYER))
25+
attributes(
26+
EntityPosition(),
27+
EntityTile(GameTileRepository.PLAYER),
28+
EntityActions(Dig::class))
2129
behaviors(InputReceiver)
2230
facets(Movable, CameraMover)
2331
}
32+
33+
fun newWall() = newGameEntityOfType(Wall) {
34+
attributes(
35+
EntityPosition(),
36+
BlockOccupier,
37+
EntityTile(GameTileRepository.WALL))
38+
facets(Diggable)
39+
}
2440
}
41+

src/main/kotlin/org/hexworks/cavesofzircon/builders/GameBlockFactory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ object GameBlockFactory {
66

77
fun floor() = GameBlock(GameTileRepository.FLOOR)
88

9-
fun wall() = GameBlock(GameTileRepository.WALL)
9+
fun wall() = GameBlock.createWith(EntityFactory.newWall())
1010

1111
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.hexworks.cavesofzircon.commands
2+
3+
import org.hexworks.amethyst.api.entity.EntityType
4+
import org.hexworks.cavesofzircon.extensions.GameEntity
5+
import org.hexworks.cavesofzircon.world.GameContext
6+
7+
data class Dig(override val context: GameContext,
8+
override val source: GameEntity<EntityType>,
9+
override val target: GameEntity<EntityType>) : EntityAction<EntityType, EntityType>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.hexworks.cavesofzircon.commands
2+
3+
import org.hexworks.amethyst.api.entity.EntityType
4+
import org.hexworks.cavesofzircon.extensions.GameCommand
5+
import org.hexworks.cavesofzircon.extensions.GameEntity
6+
7+
interface EntityAction<S : EntityType, T : EntityType> : GameCommand<S> {
8+
9+
val target: GameEntity<T>
10+
11+
operator fun component1() = context
12+
operator fun component2() = source
13+
operator fun component3() = target
14+
}

src/main/kotlin/org/hexworks/cavesofzircon/extensions/EntityExtensions.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
package org.hexworks.cavesofzircon.extensions
22

33
import org.hexworks.amethyst.api.Attribute
4+
import org.hexworks.amethyst.api.Consumed
5+
import org.hexworks.amethyst.api.Pass
6+
import org.hexworks.amethyst.api.Response
7+
import org.hexworks.cavesofzircon.attributes.EntityActions
48
import org.hexworks.cavesofzircon.attributes.EntityPosition
59
import org.hexworks.cavesofzircon.attributes.EntityTile
10+
import org.hexworks.cavesofzircon.attributes.flags.BlockOccupier
11+
import org.hexworks.cavesofzircon.world.GameContext
612
import org.hexworks.cobalt.datatypes.extensions.map
713
import org.hexworks.cobalt.datatypes.extensions.orElseThrow
814
import org.hexworks.zircon.api.data.Tile
@@ -16,9 +22,25 @@ var AnyGameEntity.position
1622
}
1723
}
1824

25+
val AnyGameEntity.occupiesBlock: Boolean
26+
get() = findAttribute(BlockOccupier::class).isPresent
27+
1928
val AnyGameEntity.tile: Tile
2029
get() = this.tryToFindAttribute(EntityTile::class).tile
2130

2231
fun <T : Attribute> AnyGameEntity.tryToFindAttribute(klass: KClass<T>): T = findAttribute(klass).orElseThrow {
2332
NoSuchElementException("Entity '$this' has no property with type '${klass.simpleName}'.")
2433
}
34+
35+
fun AnyGameEntity.tryActionsOn(context: GameContext, target: AnyGameEntity): Response {
36+
var result: Response = Pass
37+
findAttribute(EntityActions::class).map {
38+
it.createActionsFor(context, this, target).forEach { action ->
39+
if (target.executeCommand(action) is Consumed) {
40+
result = Consumed
41+
return@forEach
42+
}
43+
}
44+
}
45+
return result
46+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.hexworks.cavesofzircon.systems
2+
3+
import org.hexworks.amethyst.api.Consumed
4+
import org.hexworks.amethyst.api.base.BaseFacet
5+
import org.hexworks.amethyst.api.entity.EntityType
6+
import org.hexworks.cavesofzircon.commands.Dig
7+
import org.hexworks.cavesofzircon.extensions.GameCommand
8+
import org.hexworks.cavesofzircon.world.GameContext
9+
10+
object Diggable : BaseFacet<GameContext>() {
11+
12+
override fun executeCommand(command: GameCommand<out EntityType>) = command.responseWhenCommandIs(Dig::class) { (context, _, target) ->
13+
context.world.removeEntity(target)
14+
Consumed
15+
}
16+
}

0 commit comments

Comments
 (0)