129 lines
4.4 KiB
Java
129 lines
4.4 KiB
Java
package electroblob.wizardry.data;
|
|
|
|
import electroblob.wizardry.Wizardry;
|
|
import electroblob.wizardry.command.SpellEmitter;
|
|
import electroblob.wizardry.packet.PacketEmitterData;
|
|
import electroblob.wizardry.packet.WizardryPacketHandler;
|
|
import electroblob.wizardry.spell.Spell;
|
|
import electroblob.wizardry.util.NBTExtras;
|
|
import electroblob.wizardry.util.SpellModifiers;
|
|
import net.minecraft.entity.player.EntityPlayerMP;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.nbt.NBTTagList;
|
|
import net.minecraft.util.EnumFacing;
|
|
import net.minecraft.world.World;
|
|
import net.minecraft.world.storage.WorldSavedData;
|
|
import net.minecraftforge.common.util.Constants;
|
|
import net.minecraftforge.event.world.WorldEvent;
|
|
import net.minecraftforge.fml.common.Mod;
|
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
|
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
|
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Class responsible for storing and keeping track of {@link SpellEmitter}s. Each world has its own instance of
|
|
* {@code SpellEmitterData} which can be retrieved using {@link SpellEmitterData#get(World)}.<br>
|
|
* <br>
|
|
* To add a new {@code SpellEmitter}, use {@link SpellEmitter#add(Spell, World, double, double, double, EnumFacing, int, SpellModifiers)}.
|
|
*
|
|
* @since Wizardry 4.2
|
|
* @author Electroblob
|
|
*/
|
|
@Mod.EventBusSubscriber
|
|
public class SpellEmitterData extends WorldSavedData {
|
|
|
|
public static final String NAME = Wizardry.MODID + "_spell_emitters";
|
|
|
|
private final List<SpellEmitter> emitters = new ArrayList<>();
|
|
|
|
private NBTTagList emitterTags = null;
|
|
|
|
// Required constructors
|
|
public SpellEmitterData(){
|
|
this(NAME);
|
|
}
|
|
|
|
public SpellEmitterData(String name){
|
|
super(name);
|
|
}
|
|
|
|
/** Returns the spell emitter data for this world, or creates a new instance if it doesn't exist yet. */
|
|
public static SpellEmitterData get(World world){
|
|
|
|
SpellEmitterData instance = (SpellEmitterData)world.getPerWorldStorage().getOrLoadData(SpellEmitterData.class, NAME);
|
|
|
|
if(instance == null){
|
|
instance = new SpellEmitterData();
|
|
world.getPerWorldStorage().setData(NAME, instance);
|
|
}else if(instance.emitters.isEmpty() && instance.emitterTags != null){
|
|
instance.loadEmitters(world);
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
|
|
/** Sends the active spell emitters for this world to the specified player's client. */
|
|
public void sync(EntityPlayerMP player){
|
|
PacketEmitterData.Message msg = new PacketEmitterData.Message(emitters);
|
|
WizardryPacketHandler.net.sendTo(msg, player);
|
|
Wizardry.logger.info("Synchronising spell emitters for " + player.getName());
|
|
}
|
|
|
|
/** Adds the given {@link SpellEmitter} to the list of emitters for this {@code SpellEmitterData}. */
|
|
public void add(SpellEmitter emitter){
|
|
emitters.add(emitter);
|
|
markDirty();
|
|
}
|
|
|
|
@Override
|
|
public void readFromNBT(NBTTagCompound nbt){
|
|
emitterTags = nbt.getTagList("emitters", Constants.NBT.TAG_COMPOUND);
|
|
}
|
|
|
|
private void loadEmitters(World world){
|
|
emitters.clear();
|
|
emitters.addAll(NBTExtras.NBTToList(emitterTags, (NBTTagCompound t) -> SpellEmitter.fromNBT(world, t)));
|
|
emitterTags = null; // Now we know it's loaded
|
|
}
|
|
|
|
@Override
|
|
public NBTTagCompound writeToNBT(NBTTagCompound compound){
|
|
NBTExtras.storeTagSafely(compound, "emitters", NBTExtras.listToNBT(emitters, SpellEmitter::toNBT));
|
|
return compound;
|
|
}
|
|
|
|
public static void update(World world){
|
|
SpellEmitterData data = SpellEmitterData.get(world);
|
|
if(!data.emitters.isEmpty()){
|
|
data.emitters.forEach(SpellEmitter::update);
|
|
data.emitters.removeIf(SpellEmitter::needsRemoving);
|
|
data.markDirty(); // Mark dirty if there are changes to be saved
|
|
}
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public static void tick(TickEvent.WorldTickEvent event){
|
|
if(!event.world.isRemote && event.phase == TickEvent.Phase.END){
|
|
update(event.world);
|
|
}
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public static void onWorldLoadEvent(WorldEvent.Load event){
|
|
// Called to initialise the spell emitter data when a world loads, if it isn't already.
|
|
SpellEmitterData.get(event.getWorld());
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public static void onPlayerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event){
|
|
// Needs to be done here as well as PlayerLoggedInEvent because SpellEmitterData is dimension-specific
|
|
if(event.player instanceof EntityPlayerMP){
|
|
SpellEmitterData.get(event.player.world).sync((EntityPlayerMP)event.player);
|
|
}
|
|
}
|
|
|
|
}
|