up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
package player
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// hungerManager handles the changes in hunger, exhaustion and saturation of a player.
|
||||
type hungerManager struct {
|
||||
mu sync.RWMutex
|
||||
foodLevel int
|
||||
saturationLevel float64
|
||||
exhaustionLevel float64
|
||||
foodTick int
|
||||
}
|
||||
|
||||
// newHungerManager returns a new hunger manager with the default values for food level, saturation level and
|
||||
// exhaustion level.
|
||||
func newHungerManager() *hungerManager {
|
||||
return &hungerManager{foodLevel: 20, saturationLevel: 5, foodTick: 1}
|
||||
}
|
||||
|
||||
// Food returns the current food level of a player. The level returned is guaranteed to always be between 0
|
||||
// and 20.
|
||||
func (m *hungerManager) Food() int {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.foodLevel
|
||||
}
|
||||
|
||||
// SetFood sets the food level of a player. The level passed must be in a range of 0-20. If the level passed
|
||||
// is negative, the food level will be set to 0. If the level exceeds 20, the food level will be set to 20.
|
||||
func (m *hungerManager) SetFood(level int) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
m.foodLevel = max(min(level, 20), 0)
|
||||
}
|
||||
|
||||
// AddFood adds a number of food points to the current food level of a player.
|
||||
func (m *hungerManager) AddFood(points int) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
m.foodLevel = max(min(m.foodLevel+points, 20), 0)
|
||||
}
|
||||
|
||||
// Reset resets the hunger manager to its default values, identical to those set when creating a new manager
|
||||
// using newHungerManager.
|
||||
func (m *hungerManager) Reset() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
m.foodLevel = 20
|
||||
m.saturationLevel = 5
|
||||
m.exhaustionLevel = 0
|
||||
m.foodTick = 1
|
||||
}
|
||||
|
||||
// ResetExhaustion resets the player's exhaustion level to 0. It prevents the
|
||||
// player's food level from decreasing immediately after cancelling food loss.
|
||||
func (m *hungerManager) resetExhaustion() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.exhaustionLevel = 0
|
||||
m.saturationLevel = 0
|
||||
m.foodTick = 1
|
||||
}
|
||||
|
||||
// exhaust exhausts the player by the amount of points passed. If the total exhaustion level exceeds 4, a
|
||||
// saturation point, or food point, if saturation is 0, will be subtracted.
|
||||
func (m *hungerManager) exhaust(points float64) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
m.exhaustionLevel += points
|
||||
for m.exhaustionLevel >= 4 {
|
||||
// Maximum exhaustion value is 4, so keep removing one saturation point until the exhaustion level
|
||||
// is below 4.
|
||||
m.exhaustionLevel -= 4
|
||||
m.desaturate()
|
||||
}
|
||||
}
|
||||
|
||||
// saturate saturates the player's food and saturation by the amount of points passed. Note that the total
|
||||
// saturation will never exceed the total food value.
|
||||
func (m *hungerManager) saturate(food int, saturation float64) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
m.foodLevel = max(min(m.foodLevel+food, 20), 0)
|
||||
m.saturationLevel = max(min(m.saturationLevel+saturation, float64(m.foodLevel)), 0)
|
||||
}
|
||||
|
||||
// desaturate removes one saturation point from the player. If the saturation level of the player is already
|
||||
// 0, a point will be subtracted from the food level instead. If that level, too, is already 0, nothing will
|
||||
// happen.
|
||||
func (m *hungerManager) desaturate() {
|
||||
if m.saturationLevel <= 0 && m.foodLevel != 0 {
|
||||
m.foodLevel--
|
||||
} else if m.saturationLevel > 0 {
|
||||
m.saturationLevel = max(m.saturationLevel-1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// canQuicklyRegenerate checks if the player can quickly regenerate. The function returns true if Food() returns 20
|
||||
// and the player still has saturation left.
|
||||
// The rate of regeneration is 1/0.5 seconds.
|
||||
func (m *hungerManager) canQuicklyRegenerate() bool {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
return m.foodLevel == 20 && m.saturationLevel > 0
|
||||
}
|
||||
|
||||
// canRegenerate checks if the player with the amount of food levels in the hunger manager can regenerate.
|
||||
// The function returns true if Food() returns either 18-20.
|
||||
// The rate of regeneration is 1/4 seconds.
|
||||
func (m *hungerManager) canRegenerate() bool {
|
||||
return m.Food() >= 18
|
||||
}
|
||||
|
||||
// canSprint returns true if the food level of the player is 7 or higher.
|
||||
func (m *hungerManager) canSprint() bool {
|
||||
return m.Food() > 6
|
||||
}
|
||||
|
||||
// starving checks if the player is currently considered to be starving. True is returned if Food() returns 0.
|
||||
func (m *hungerManager) starving() bool {
|
||||
return m.Food() == 0
|
||||
}
|
||||
|
||||
// StarvationDamageSource is the world.DamageSource passed when a player is
|
||||
// dealt damage from an empty food bar.
|
||||
type StarvationDamageSource struct{}
|
||||
|
||||
func (StarvationDamageSource) ReducedByArmour() bool { return false }
|
||||
func (StarvationDamageSource) ReducedByResistance() bool { return false }
|
||||
func (StarvationDamageSource) Fire() bool { return false }
|
||||
func (StarvationDamageSource) IgnoreTotem() bool { return false }
|
||||
Reference in New Issue
Block a user