Skip to content

Commit

Permalink
Add items and inventory
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-arold committed May 17, 2019
1 parent 5fdac9f commit 2db3a39
Show file tree
Hide file tree
Showing 23 changed files with 386 additions and 6 deletions.
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ version=2019.0.1-PREVIEW
kotlin_version=1.3.21
shadow_version=4.0.2

cobalt_version=2018.1.1-PREVIEW
amethyst_version=2019.0.4-PREVIEW
zircon_version=2019.0.14-PREVIEW
cobalt_version=2019.1.0-PREVIEW
amethyst_version=2019.1.0-PREVIEW
zircon_version=2019.1.0-PREVIEW

junit_version=4.12
mockito_version=1.10.19
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/org/hexworks/cavesofzircon/GameConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ object GameConfig {
// entities
const val FUNGI_PER_LEVEL = 15
const val BATS_PER_LEVEL = 10
const val ZIRCONS_PER_LEVEL = 20
const val MAXIMUM_FUNGUS_SPREAD = 20

fun buildAppConfig() = AppConfigs.newConfig()
Expand Down
34 changes: 34 additions & 0 deletions src/main/kotlin/org/hexworks/cavesofzircon/attributes/Inventory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.hexworks.cavesofzircon.attributes

import org.hexworks.amethyst.api.Attribute
import org.hexworks.cavesofzircon.extensions.GameItem
import org.hexworks.cobalt.datatypes.Identifier
import org.hexworks.cobalt.datatypes.Maybe

class Inventory(val size: Int) : Attribute {

private val currentItems = mutableListOf<GameItem>()

val items: List<GameItem>
get() = currentItems.toList()

val isEmpty: Boolean
get() = currentItems.isEmpty()

val isFull: Boolean
get() = currentItems.size >= size

fun findItemBy(id: Identifier): Maybe<GameItem> {
return Maybe.ofNullable(items.firstOrNull { it.id == id })
}

fun addItem(item: GameItem): Boolean {
return if (isFull.not()) {
currentItems.add(item)
} else false
}

fun removeItem(entity: GameItem): Boolean {
return currentItems.remove(entity)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hexworks.cavesofzircon.attributes

import org.hexworks.amethyst.api.Attribute
import org.hexworks.zircon.api.data.GraphicalTile

data class ItemIcon(val iconTile: GraphicalTile) : Attribute
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package org.hexworks.cavesofzircon.attributes.types
import org.hexworks.amethyst.api.base.BaseEntityType

object Player : BaseEntityType(
name = "player"), Combatant
name = "player"), Combatant, ItemHolder

object Wall : BaseEntityType(
name = "wall")
Expand All @@ -20,4 +20,8 @@ object StairsDown : BaseEntityType(
object StairsUp : BaseEntityType(
name = "stairs up")

object Zircon : BaseEntityType(
name = "Zircon",
description = "A small piece of Zircon. Its value is unfathomable."), Item

object FogOfWarType : BaseEntityType()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.hexworks.cavesofzircon.attributes.types

import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.attributes.EntityTile
import org.hexworks.cavesofzircon.attributes.ItemIcon
import org.hexworks.cavesofzircon.extensions.GameEntity
import org.hexworks.zircon.api.data.GraphicalTile
import org.hexworks.zircon.api.data.Tile

interface Item : EntityType

val GameEntity<Item>.tile: Tile
get() = findAttribute(EntityTile::class).get().tile

val GameEntity<Item>.iconTile: GraphicalTile
get() = findAttribute(ItemIcon::class).get().iconTile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.hexworks.cavesofzircon.attributes.types

import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.attributes.Inventory
import org.hexworks.cavesofzircon.extensions.GameItem
import org.hexworks.cavesofzircon.extensions.GameItemHolder

interface ItemHolder : EntityType

fun GameItemHolder.addItem(item: GameItem) = inventory.addItem(item)

fun GameItemHolder.removeItem(item: GameItem) = inventory.removeItem(item)

val GameItemHolder.inventory: Inventory
get() = findAttribute(Inventory::class).get()
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import org.hexworks.cavesofzircon.attributes.EntityActions
import org.hexworks.cavesofzircon.attributes.EntityPosition
import org.hexworks.cavesofzircon.attributes.EntityTile
import org.hexworks.cavesofzircon.attributes.FungusSpread
import org.hexworks.cavesofzircon.attributes.Inventory
import org.hexworks.cavesofzircon.attributes.ItemIcon
import org.hexworks.cavesofzircon.attributes.Vision
import org.hexworks.cavesofzircon.attributes.flags.BlockOccupier
import org.hexworks.cavesofzircon.attributes.flags.VisionBlocker
Expand All @@ -17,6 +19,7 @@ import org.hexworks.cavesofzircon.attributes.types.Player
import org.hexworks.cavesofzircon.attributes.types.StairsDown
import org.hexworks.cavesofzircon.attributes.types.StairsUp
import org.hexworks.cavesofzircon.attributes.types.Wall
import org.hexworks.cavesofzircon.attributes.types.Zircon
import org.hexworks.cavesofzircon.commands.Attack
import org.hexworks.cavesofzircon.commands.Dig
import org.hexworks.cavesofzircon.entities.FogOfWar
Expand All @@ -26,12 +29,17 @@ import org.hexworks.cavesofzircon.systems.Destructible
import org.hexworks.cavesofzircon.systems.Diggable
import org.hexworks.cavesofzircon.systems.FungusGrowth
import org.hexworks.cavesofzircon.systems.InputReceiver
import org.hexworks.cavesofzircon.systems.InventoryInspector
import org.hexworks.cavesofzircon.systems.ItemDropper
import org.hexworks.cavesofzircon.systems.ItemPicker
import org.hexworks.cavesofzircon.systems.Movable
import org.hexworks.cavesofzircon.systems.StairClimber
import org.hexworks.cavesofzircon.systems.StairDescender
import org.hexworks.cavesofzircon.systems.Wanderer
import org.hexworks.cavesofzircon.world.Game
import org.hexworks.cavesofzircon.world.GameContext
import org.hexworks.zircon.api.GraphicalTilesetResources
import org.hexworks.zircon.api.Tiles

fun <T : EntityType> newGameEntityOfType(type: T, init: EntityBuilder<T, GameContext>.() -> Unit) =
Entities.newEntityOfType(type, init)
Expand Down Expand Up @@ -69,9 +77,11 @@ object EntityFactory {
attackValue = 10,
defenseValue = 5),
EntityTile(GameTileRepository.PLAYER),
EntityActions(Dig::class, Attack::class))
EntityActions(Dig::class, Attack::class),
Inventory(10))
behaviors(InputReceiver)
facets(Movable, CameraMover, StairClimber, StairDescender, Attackable, Destructible)
facets(Movable, CameraMover, StairClimber, StairDescender, Attackable, Destructible, ItemPicker,
InventoryInspector, ItemDropper)
}

fun newFungus(fungusSpread: FungusSpread = FungusSpread()) = newGameEntityOfType(Fungus) {
Expand Down Expand Up @@ -99,5 +109,14 @@ object EntityFactory {
facets(Movable, Attackable, Destructible)
behaviors(Wanderer)
}

fun newZircon() = newGameEntityOfType(Zircon) {
attributes(ItemIcon(Tiles.newBuilder()
.withName("white gem")
.withTileset(GraphicalTilesetResources.nethack16x16())
.buildGraphicTile()),
EntityPosition(),
EntityTile(GameTileRepository.ZIRCON))
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ object GameColors {
val BAT_COLOR = TileColors.fromString("#2348b2")

val ACCENT_COLOR = TileColors.fromString("#FFCD22")
val ZIRCON_COLOR = TileColors.fromString("#dddddd")

val UNREVEALED_COLOR = TileColors.fromString("#000000")
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ object GameTileRepository {
.withForegroundColor(GameColors.BAT_COLOR)
.buildCharacterTile()

val ZIRCON = Tiles.newBuilder()
.withCharacter(',')
.withBackgroundColor(GameColors.FLOOR_BACKGROUND)
.withForegroundColor(GameColors.ZIRCON_COLOR)
.buildCharacterTile()

val UNREVEALED = Tiles.newBuilder()
.withCharacter(' ')
.withBackgroundColor(GameColors.UNREVEALED_COLOR)
Expand Down
13 changes: 13 additions & 0 deletions src/main/kotlin/org/hexworks/cavesofzircon/commands/DropItem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.hexworks.cavesofzircon.commands

import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.extensions.GameCommand
import org.hexworks.cavesofzircon.extensions.GameItem
import org.hexworks.cavesofzircon.extensions.GameItemHolder
import org.hexworks.cavesofzircon.world.GameContext
import org.hexworks.zircon.api.data.impl.Position3D

data class DropItem(override val context: GameContext,
override val source: GameItemHolder,
val item: GameItem,
val position: Position3D) : GameCommand<EntityType>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.hexworks.cavesofzircon.commands

import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.extensions.GameCommand
import org.hexworks.cavesofzircon.extensions.GameItemHolder
import org.hexworks.cavesofzircon.world.GameContext
import org.hexworks.zircon.api.data.impl.Position3D

data class InspectInventory(override val context: GameContext,
override val source: GameItemHolder,
val position: Position3D) : GameCommand<EntityType>
14 changes: 14 additions & 0 deletions src/main/kotlin/org/hexworks/cavesofzircon/commands/PickItemUp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.hexworks.cavesofzircon.commands

import org.hexworks.cavesofzircon.attributes.types.ItemHolder
import org.hexworks.cavesofzircon.extensions.GameCommand
import org.hexworks.cavesofzircon.extensions.GameItemHolder
import org.hexworks.cavesofzircon.world.GameContext
import org.hexworks.zircon.api.data.impl.Position3D

/**
* A [GameCommand] representing [source] picking up an item at [position].
*/
data class PickItemUp(override val context: GameContext,
override val source: GameItemHolder,
val position: Position3D) : GameCommand<ItemHolder>
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
@file:Suppress("UNCHECKED_CAST")

package org.hexworks.cavesofzircon.extensions

import org.hexworks.amethyst.api.Attribute
import org.hexworks.amethyst.api.Consumed
import org.hexworks.amethyst.api.Pass
import org.hexworks.amethyst.api.Response
import org.hexworks.amethyst.api.entity.Entity
import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.attributes.EntityActions
import org.hexworks.cavesofzircon.attributes.EntityPosition
import org.hexworks.cavesofzircon.attributes.EntityTile
import org.hexworks.cavesofzircon.attributes.flags.BlockOccupier
import org.hexworks.cavesofzircon.attributes.flags.VisionBlocker
import org.hexworks.cavesofzircon.attributes.types.Combatant
import org.hexworks.cavesofzircon.attributes.types.Item
import org.hexworks.cavesofzircon.attributes.types.Player
import org.hexworks.cavesofzircon.attributes.types.combatStats
import org.hexworks.cavesofzircon.world.GameContext
import org.hexworks.cobalt.datatypes.extensions.map
import org.hexworks.cobalt.datatypes.extensions.orElseThrow
import org.hexworks.zircon.api.data.Tile
import kotlin.reflect.KClass
import kotlin.reflect.full.isSuperclassOf

var AnyGameEntity.position
get() = tryToFindAttribute(EntityPosition::class).position
Expand All @@ -35,6 +41,10 @@ val AnyGameEntity.tile: Tile
val AnyGameEntity.isPlayer: Boolean
get() = this.type == Player

inline fun <reified T : EntityType> Iterable<AnyGameEntity>.filterType(): List<Entity<T, GameContext>> {
return filter { T::class.isSuperclassOf(it.type::class) }.toList() as List<Entity<T, GameContext>>
}

val AnyGameEntity.blocksVision: Boolean
get() = this.findAttribute(VisionBlocker::class).isPresent

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package org.hexworks.cavesofzircon.extensions
import org.hexworks.amethyst.api.Command
import org.hexworks.amethyst.api.entity.Entity
import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.attributes.types.Item
import org.hexworks.cavesofzircon.attributes.types.ItemHolder
import org.hexworks.cavesofzircon.world.GameContext

/**
Expand All @@ -19,3 +21,7 @@ typealias GameEntity<T> = Entity<T, GameContext>
* Specializes [Command] with our [GameContext] type.
*/
typealias GameCommand<T> = Command<T, GameContext>

typealias GameItem = GameEntity<Item>

typealias GameItemHolder = GameEntity<ItemHolder>
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package org.hexworks.cavesofzircon.systems
import org.hexworks.amethyst.api.base.BaseBehavior
import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.attributes.types.Player
import org.hexworks.cavesofzircon.commands.InspectInventory
import org.hexworks.cavesofzircon.commands.MoveDown
import org.hexworks.cavesofzircon.commands.MoveTo
import org.hexworks.cavesofzircon.commands.MoveUp
import org.hexworks.cavesofzircon.commands.PickItemUp
import org.hexworks.cavesofzircon.extensions.GameEntity
import org.hexworks.cavesofzircon.extensions.position
import org.hexworks.cavesofzircon.world.GameContext
Expand All @@ -29,6 +31,8 @@ object InputReceiver : BaseBehavior<GameContext>() {
KeyCode.KEY_D -> player.moveTo(currentPos.withRelativeX(1), context)
KeyCode.KEY_R -> player.moveUp(context)
KeyCode.KEY_F -> player.moveDown(context)
KeyCode.KEY_P -> player.pickItemUp(currentPos, context)
KeyCode.KEY_I -> player.inspectInventory(currentPos, context)
else -> {
logger.debug("UI Event ($uiEvent) does not have a corresponding command, it is ignored.")
}
Expand All @@ -37,6 +41,14 @@ object InputReceiver : BaseBehavior<GameContext>() {
return true
}

private fun GameEntity<Player>.inspectInventory(position: Position3D, context: GameContext) {
executeCommand(InspectInventory(context, this, position))
}

private fun GameEntity<Player>.pickItemUp(position: Position3D, context: GameContext) {
executeCommand(PickItemUp(context, this, position))
}

private fun GameEntity<Player>.moveTo(position: Position3D, context: GameContext) {
executeCommand(MoveTo(context, this, position))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.hexworks.cavesofzircon.systems

import org.hexworks.amethyst.api.Consumed
import org.hexworks.amethyst.api.base.BaseFacet
import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.GameConfig
import org.hexworks.cavesofzircon.attributes.types.inventory
import org.hexworks.cavesofzircon.commands.DropItem
import org.hexworks.cavesofzircon.commands.InspectInventory
import org.hexworks.cavesofzircon.extensions.GameCommand
import org.hexworks.cavesofzircon.view.fragment.InventoryFragment
import org.hexworks.cavesofzircon.world.GameContext
import org.hexworks.zircon.api.Components
import org.hexworks.zircon.api.Sizes
import org.hexworks.zircon.api.builder.component.ModalBuilder
import org.hexworks.zircon.api.component.ComponentAlignment.BOTTOM_LEFT
import org.hexworks.zircon.api.extensions.onComponentEvent
import org.hexworks.zircon.api.uievent.ComponentEventType.ACTIVATED
import org.hexworks.zircon.api.uievent.Processed
import org.hexworks.zircon.internal.component.modal.EmptyModalResult

object InventoryInspector : BaseFacet<GameContext>() {

val DIALOG_SIZE = Sizes.create(33, 14)

override fun executeCommand(command: GameCommand<out EntityType>) = command
.responseWhenCommandIs(InspectInventory::class) { (context, itemHolder, position) ->

val screen = context.screen

val fragment = InventoryFragment(itemHolder.inventory, DIALOG_SIZE.width - 3) { item ->
itemHolder.executeCommand(DropItem(context, itemHolder, item, position))
}

val panel = Components.panel()
.withSize(DIALOG_SIZE)
.wrapWithBox(true)
.wrapWithShadow(true)
.withTitle("Inventory")
.build()

panel.addFragment(fragment)

val modal = ModalBuilder.newBuilder<EmptyModalResult>()
.withParentSize(screen.size)
.withComponent(panel)
.build()

panel.addComponent(Components.button()
.withText("Close")
.withAlignmentWithin(panel, BOTTOM_LEFT)
.build().apply {
onComponentEvent(ACTIVATED) {
modal.close(EmptyModalResult)
Processed
}
})

modal.applyColorTheme(GameConfig.THEME)
screen.openModal(modal)
Consumed
}

}
Loading

0 comments on commit 2db3a39

Please sign in to comment.