/**
Copyright (C) <2015> <coolAlias>
This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such,
you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package zeldaswordskills.world.crisis;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import zeldaswordskills.ZSSMain;
/**
*
* Abstract crisis class provides basic framework for an updating and self-terminating event.
*
* After a crisis is constructed, {@link #beginCrisis(World)} must be called to initiate the
* crisis, after which point it will run its course automatically so long as {@link #onUpdate(World)}
* is called every tick until {@link #isFinished()} returns true.
*
*/
public abstract class AbstractCrisis
{
/** Event timer; when it reaches zero, the crisis is finished */
protected int eventTimer = 0;
/** Crisis update tick will be called when eventTimer reaches this value */
protected int nextTick = 0;
/**
* Returns true when the crisis has completed
*/
public final boolean isFinished() {
return eventTimer < 0;
}
/**
* Schedules an update n ticks in the future
*/
protected final void scheduleUpdateTick(int n) {
if (n < 0) {
ZSSMain.logger.warn("Oops! Scheduling a crisis tick with n less than zero.");
}
nextTick = (n > 0 ? eventTimer - n : 0);
}
/**
* Call every tick while battle is in progress
*/
public final void onUpdate(World world) {
if (eventTimer > 0) {
--eventTimer;
if (eventTimer % 20 == 0 && canCrisisConclude(world)) {
eventTimer = 0;
} else if (eventTimer < 40) {
eventTimer += 40;
}
if (eventTimer == 0) {
endCrisis(world);
eventTimer = -1;
} else if (eventTimer == nextTick) {
onUpdateTick(world);
}
} else {
ZSSMain.logger.warn("Unexpected timer value: crisis terminated but not handled");
eventTimer = -1;
}
}
/**
* Allows sub-classes to define behavior during update ticks, but only if
* an update tick is scheduled using nextTick. Note that eventTimer counts
* down, and an update tick will be called when eventTimer equals nextTick.
*/
protected abstract void onUpdateTick(World world);
/**
* This method should always be called after a crisis is first constructed (not
* when loaded from NBT), allowing crisis to set up before it begins updating.
* If an update tick needs to be scheduled, the first one should be scheduled here.
*/
public abstract void beginCrisis(World world);
/**
* Handles everything that happens at the end of a crisis, such as spawning xp,
* playing victory music, etc.
*/
protected abstract void endCrisis(World world);
/**
* Called every 20 ticks to check if the crisis should conclude before the eventTimer expires;
* for example, if the crisis is about defeating enemies and they are all dead, it should conclude
*/
protected abstract boolean canCrisisConclude(World world);
/**
* Writes the crisis data to NBT
*/
public void writeToNBT(NBTTagCompound compound) {
compound.setInteger("eventTimer", eventTimer);
compound.setInteger("nextTick", nextTick);
}
/**
* Reads the crisis data from NBT
*/
public void readFromNBT(NBTTagCompound compound) {
eventTimer = compound.getInteger("eventTimer");
nextTick = compound.getInteger("nextTick");
}
}