hestia-rsps / hestia

An open-source Kotlin game server.
BSD 3-Clause "New" or "Revised" License
16 stars 4 forks source link

Delayed reset system #54

Open GregHib opened 4 years ago

GregHib commented 4 years ago

Whether it's doors opening/closing, entities respawning, shooting star starting/stopping. Lots of features follow this delayed reactivate/respawn pattern so it makes sense to have a reusable respawning system.

abstract class Respawnable : Component() {
    var ticks = 0
} 
abstract class RespawnSystem(clazz: Class<out Respawnable>) : DelayedIteratingSystem(Aspect.all(clazz)) {
    override fun process(entityId: Int) {
        // TODO - decrease ticks. If ticks <= 0 then disable the component
    } 
} 

If a component is toggled, does inserted/removed get called again?

GregHib commented 4 years ago

ComponentMapper.set(entityId, boolean) is just a helper function for adding and removing an entity component, which does call inserted and removed.

GregHib commented 4 years ago

Working POC

abstract class Resettable : Component() {
    var cooldown = 0f
}

abstract class ResettableSystem<T: Resettable>(aspect: com.artemis.Aspect.Builder) : DelayedIteratingSystem(aspect) {

    abstract var resettableMapper: ComponentMapper<T>

    override fun processDelta(entityId: Int, accumulatedDelta: Float) {
        val resettable = resettableMapper.get(entityId)
        resettable.cooldown -= accumulatedDelta
    }

    override fun getRemainingDelay(entityId: Int): Float {
        val resettable = resettableMapper.get(entityId)
        return resettable.cooldown
    }

    override fun processExpired(entityId: Int) {
        val resettable = resettableMapper.get(entityId)
        if(resettable.cooldown > 0) {
            offerDelay(resettable.cooldown)
        } else {
            resettableMapper.remove(entityId)
        }
    }
}

Usage

class TestComponent(ticks: Int) : Resettable() {
    init {
       cooldown = 0.6f * ticks
    }
}
world.setDelta(0.6f)//600ms