diff --git a/src/com/massivecraft/massivecore/HeatData.java b/src/com/massivecraft/massivecore/HeatData.java new file mode 100644 index 00000000..1d41bbaa --- /dev/null +++ b/src/com/massivecraft/massivecore/HeatData.java @@ -0,0 +1,85 @@ +package com.massivecraft.massivecore; + +public final class HeatData +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + public static final transient double HEAT_MIN = 0D; + public static final transient double HEAT_HIGH = 1D; + public static final transient long MILLIS_CALC_EPSILON = 50; + + // -------------------------------------------- // + // FIELDS: RAW + // -------------------------------------------- // + + private final double heat; + public double getHeat() { return this.heat; } + + private final long lastCalcMillis; + public long getLastCalcMillis() { return this.lastCalcMillis; } + + // -------------------------------------------- // + // FIELDS: INSPECT + // -------------------------------------------- // + + public double getOverheat() + { + return this.getHeat() - HEAT_HIGH; + } + + public boolean isOverheated() + { + return this.getOverheat() > 0; + } + + // -------------------------------------------- // + // FIELDS: WITH + // -------------------------------------------- // + + public HeatData withHeat(double heat) { return new HeatData(heat, lastCalcMillis); } + public HeatData withLastCalcMillis(long lastCalcMillis) { return new HeatData(heat, lastCalcMillis); } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + private HeatData(double heat, long lastCalcMillis) + { + this.heat = Math.max(0, heat); + this.lastCalcMillis = lastCalcMillis; + } + + private HeatData() + { + this.heat = 0; + this.lastCalcMillis = 0; + } + + // -------------------------------------------- // + // FACTORY: VALUE OF + // -------------------------------------------- // + + public static HeatData valueOf(double heat, long lastCalcMillis) + { + return new HeatData(heat, lastCalcMillis); + } + + // -------------------------------------------- // + // FACTORY: RECALCULATED + // -------------------------------------------- // + + public HeatData recalculated(long now, double heatPerMilli) + { + if (this.lastCalcMillis + MILLIS_CALC_EPSILON >= now) return this; + + long deltaMillis = now - this.lastCalcMillis; + double heatDelta = heatPerMilli * deltaMillis; + double heatTarget = this.heat + heatDelta; + heatTarget = Math.max(0, heatTarget); + + return valueOf(heatTarget, now); + } + +} diff --git a/src/com/massivecraft/massivecore/Heatable.java b/src/com/massivecraft/massivecore/Heatable.java new file mode 100644 index 00000000..8747b9f3 --- /dev/null +++ b/src/com/massivecraft/massivecore/Heatable.java @@ -0,0 +1,107 @@ +package com.massivecraft.massivecore; + +public abstract class Heatable +{ + // -------------------------------------------- // + // ABSTRACT + // -------------------------------------------- // + + public abstract HeatData getData(); + public abstract void setData(HeatData data); + + public abstract double getHeatPerMilli(); + public abstract double getHeatPerExecution(); + + // -------------------------------------------- // + // CUSTOM + // -------------------------------------------- // + + private HeatData getRecalculatedData(double heatPerMilli) + { + long now = System.currentTimeMillis(); + HeatData data = this.getData().recalculated(now, heatPerMilli); + this.setData(data); + return data; + } + + public void addHeat(double heatPerMilli, double heat) + { + long now = System.currentTimeMillis(); + HeatData data = this.getData().recalculated(now, heatPerMilli); + data = data.withHeat(data.getHeat() + heat); + this.setData(data); + } + + public double getHeat(double heatPerMilli) + { + HeatData data = getRecalculatedData(heatPerMilli); + return data.getHeat(); + } + + public boolean isOverheated(double heatPerMilli) + { + HeatData data = getRecalculatedData(heatPerMilli); + return data.isOverheated(); + } + + public double getOverheat(double heatPerMilli) + { + HeatData data = getRecalculatedData(heatPerMilli); + return data.getOverheat(); + } + + public long getCooldownMillisLeft(double heatPerMilli) + { + double overheat = this.getOverheat(heatPerMilli); + return (long) (-overheat / heatPerMilli); + } + + // -------------------------------------------- // + // DEFAULT + // -------------------------------------------- // + + public void addHeat(double heat) + { + this.addHeat(this.getHeatPerMilli(), heat); + } + + public void addHeat() + { + this.addHeat(this.getHeatPerExecution()); + } + + public double getHeat() + { + return this.getHeat(this.getHeatPerMilli()); + } + + public boolean isOverheated() + { + return this.isOverheated(this.getHeatPerMilli()); + } + + public double getOverheat() + { + return this.getOverheat(this.getHeatPerMilli()); + } + + public long getCooldownMillisLeft() + { + return this.getCooldownMillisLeft(this.getHeatPerMilli()); + } + + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // + + public static double calcHeatPerExecution(long executionCount, long periodMillis) + { + return 1D / (double)executionCount; + } + + public static double calcHeatPerMilli(long executionCount, long periodMillis) + { + return - 1D / (double)periodMillis; + } + +}