blob: 125e20f4d0d5cd01600ec12e6d851e12bd6d2a8c [file] [log] [blame] [raw]
package li.cil.oc.server.component
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.internal
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.prefab
import net.minecraft.enchantment.Enchantment
import net.minecraft.enchantment.EnchantmentHelper
import net.minecraft.init.Items
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._
class UpgradeExperience(val host: EnvironmentHost with internal.Agent) extends prefab.ManagedEnvironment {
override val node = api.Network.newNode(this, Visibility.Network).
withComponent("experience").
withConnector(30 * Settings.get.bufferPerLevel).
create()
var experience = 0.0
var level = 0
def xpForLevel(level: Int): Double =
if (level == 0) 0
else Settings.get.baseXpToLevel + Math.pow(level * Settings.get.constantXpGrowth, Settings.get.exponentialXpGrowth)
def xpForNextLevel = xpForLevel(level + 1)
def addExperience(value: Double) {
if (level < 30) {
experience = experience + value
if (experience >= xpForNextLevel) {
updateXpInfo()
}
}
}
def updateXpInfo() {
// xp(level) = base + (level * const) ^ exp
// pow(xp(level) - base, 1/exp) / const = level
level = math.min((Math.pow(experience - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt, 30)
if (node != null) {
node.setLocalBufferSize(Settings.get.bufferPerLevel * level)
}
}
@Callback(direct = true, doc = """function():number -- The current level of experience stored in this experience upgrade.""")
def level(context: Context, args: Arguments): Array[AnyRef] = {
val xpNeeded = xpForNextLevel - xpForLevel(level)
val xpProgress = math.max(0, experience - xpForLevel(level))
result(level + xpProgress / xpNeeded)
}
@Callback(doc = """function():boolean -- Tries to consume an enchanted item to add experience to the upgrade.""")
def consume(context: Context, args: Arguments): Array[AnyRef] = {
val stack = host.mainInventory.getStackInSlot(host.selectedSlot)
if (stack == null || stack.stackSize < 1) {
return result(Unit, "no item")
}
var xp = 0
if (stack.getItem == Items.experience_bottle) {
xp += 3 + host.world.rand.nextInt(5) + host.world.rand.nextInt(5)
}
else {
for ((id: Int, level: Int) <- EnchantmentHelper.getEnchantments(stack)) {
val enchantment = Enchantment.enchantmentsList(id)
if (enchantment != null) {
xp += enchantment.getMinEnchantability(level)
}
}
if (xp <= 0) {
return result(Unit, "could not extract experience from item")
}
}
val consumed = host.mainInventory().decrStackSize(host.selectedSlot, 1)
if (consumed == null || consumed.stackSize < 1) {
return result(Unit, "could not consume item")
}
addExperience(xp * Settings.get.constantXpGrowth)
result(true)
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
nbt.setDouble(Settings.namespace + "xp", experience)
}
override def load(nbt: NBTTagCompound) {
super.load(nbt)
experience = nbt.getDouble(Settings.namespace + "xp") max 0
updateXpInfo()
}
}