That's one heck of a commit you've got there...
I may have got a bit behind with version control. A lot behind, in fact. Maybe I'll go back and split this sometime - then again, I probably won't. But hey, at least it's here!
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
package electroblob.wizardry.data;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.event.SpellCastEvent;
|
||||
import electroblob.wizardry.packet.PacketDispenserCastSpell;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.None;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
|
||||
/**
|
||||
* Base class for {@link DispenserCastingData}. Originally this was written because command blocks had a similar system,
|
||||
* but that was later removed in favour of spell emitters - however, this class has been kept so that others can use it
|
||||
* for different spellcasting blocks if they wish.
|
||||
*
|
||||
* @since Wizardry 4.2
|
||||
* @author Electroblob
|
||||
*/
|
||||
public abstract class BlockCastingData<T extends TileEntity> implements INBTSerializable<NBTTagCompound> {
|
||||
|
||||
/** The tile entity this BlockCastingData instance belongs to. */
|
||||
protected final T tileEntity;
|
||||
|
||||
/** The continuous spell this tile entity is currently casting, or the {@link None} spell if it is not casting. */
|
||||
protected Spell spell;
|
||||
/** The coordinates of the current continuous spell's origin. */
|
||||
protected double x, y, z;
|
||||
/** The time for which this tile entity has been casting a continuous spell. Increments by 1 each tick. */
|
||||
protected int castingTick;
|
||||
/** SpellModifiers object for the current continuous spell. */
|
||||
protected SpellModifiers modifiers;
|
||||
|
||||
public BlockCastingData(T tileEntity){
|
||||
this.tileEntity = tileEntity;
|
||||
this.spell = Spells.none;
|
||||
this.modifiers = new SpellModifiers();
|
||||
this.castingTick = 0;
|
||||
}
|
||||
|
||||
/** Returns whether this tile entity is currently casting a continuous spell. */
|
||||
public boolean isCasting(){
|
||||
return this.spell != null && this.spell != Spells.none;
|
||||
}
|
||||
|
||||
/** Returns the continuous spell this tile entity is currently casting, or the {@link None} spell if it isn't
|
||||
* casting anything. */
|
||||
public Spell currentlyCasting(){
|
||||
return spell;
|
||||
}
|
||||
|
||||
/** Starts casting the given continuous spell from this tile entity. */
|
||||
protected void startCasting(Spell spell, double x, double y, double z, SpellModifiers modifiers){
|
||||
|
||||
if(!spell.isContinuous){
|
||||
Wizardry.logger.warn("Tried to start casting a continuous spell from a tile entity, but the given spell was not continuous!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.spell = spell;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.castingTick = 0;
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
/** Stops casting the current spell. */
|
||||
protected void stopCasting(){
|
||||
this.spell = Spells.none;
|
||||
this.castingTick = 0;
|
||||
this.modifiers.reset();
|
||||
}
|
||||
|
||||
/** Stops casting the current spell and sends a packet to clients to update them. If called client-side, this just
|
||||
* delegates to {@link BlockCastingData#stopCasting()}. */
|
||||
protected void stopCastingAndNotify(){
|
||||
|
||||
stopCasting();
|
||||
|
||||
if(!tileEntity.getWorld().isRemote){
|
||||
IMessage msg = new PacketDispenserCastSpell.Message(x, y, z, getDirection(), tileEntity.getPos(), spell, 0, modifiers);
|
||||
WizardryPacketHandler.net.sendToDimension(msg, tileEntity.getWorld().provider.getDimension());
|
||||
}
|
||||
}
|
||||
|
||||
/** Called once per tick to update the block casting data. <b>This is not called automatically</b>, subclasses must
|
||||
* do so using their own tick event handlers. */
|
||||
protected void update(){
|
||||
|
||||
if(this.tileEntity.isInvalid()){
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.isCasting() && this.spell.isContinuous){
|
||||
|
||||
// If the dispenser has stopped receiving power, the spell stops immediately.
|
||||
if(!shouldContinueCasting()){
|
||||
this.stopCasting(); // This seems to work fine on both sides, so no point sending a packet
|
||||
return;
|
||||
}
|
||||
|
||||
EnumFacing direction = getDirection();
|
||||
|
||||
if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(getSource(), spell, tileEntity.getWorld(),
|
||||
x, y, z, direction, modifiers, castingTick))){
|
||||
// When the event is canceled client-side, this will stop the spell on the client only, as specified in
|
||||
// the javadoc for SpellCastEvent.Tick.
|
||||
this.stopCastingAndNotify();
|
||||
return;
|
||||
}
|
||||
|
||||
this.spell.cast(tileEntity.getWorld(), x, y, z, direction, castingTick, -1, modifiers);
|
||||
|
||||
castingTick++;
|
||||
|
||||
}else{
|
||||
this.castingTick = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the direction to cast the current spell in. */
|
||||
protected abstract EnumFacing getDirection();
|
||||
|
||||
/** Returns the source of spells cast from this block. */
|
||||
protected abstract SpellCastEvent.Source getSource();
|
||||
|
||||
/** Called each tick during continuous spell casting to determine if the spell should continue or stop. */
|
||||
protected abstract boolean shouldContinueCasting();
|
||||
|
||||
@Override
|
||||
public NBTTagCompound serializeNBT(){
|
||||
|
||||
NBTTagCompound nbt = new NBTTagCompound();
|
||||
|
||||
nbt.setInteger("spell", spell.metadata());
|
||||
nbt.setInteger("castingTick", castingTick);
|
||||
nbt.setTag("modifiers", modifiers.toNBT());
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(NBTTagCompound nbt){
|
||||
|
||||
if(nbt != null){
|
||||
|
||||
this.spell = Spell.byMetadata(nbt.getInteger("spell"));
|
||||
this.castingTick = nbt.getInteger("castingTick");
|
||||
this.modifiers = SpellModifiers.fromNBT(nbt.getCompoundTag("modifiers"));
|
||||
}
|
||||
}
|
||||
|
||||
// The two methods below broke EVERYTHING, somehow they made the server think it was the client...
|
||||
|
||||
// // Only fired server-side
|
||||
// @SubscribeEvent
|
||||
// public static void onWorldTickEvent(TickEvent.WorldTickEvent event){
|
||||
//
|
||||
// if(!event.world.isRemote && event.phase == TickEvent.Phase.END){
|
||||
// // This will fire once for each dimension, but since we want dispenser-casting to work in all dimensions,
|
||||
// // this is correct (the loaded tile entity list will of course be different in each case.
|
||||
// this.update();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Only called client-side
|
||||
// @SubscribeEvent
|
||||
// public static void onClientTickEvent(TickEvent.ClientTickEvent event){
|
||||
// World world = net.minecraft.client.Minecraft.getMinecraft().world;
|
||||
// if(event.phase == TickEvent.Phase.END && !net.minecraft.client.Minecraft.getMinecraft().isGamePaused()
|
||||
// && world != null){
|
||||
// this.update();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user