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,128 @@
|
||||
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){
|
||||
compound.setTag("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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user